<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://wiki.anime-sharing.com/hgames/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Denikson</id>
		<title>Hgames Wiki - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.anime-sharing.com/hgames/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Denikson"/>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Special:Contributions/Denikson"/>
		<updated>2026-07-19T11:57:41Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.27.1</generator>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=User:Denikson&amp;diff=22764</id>
		<title>User:Denikson</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=User:Denikson&amp;diff=22764"/>
				<updated>2017-11-01T15:25:37Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= About denikson =&lt;br /&gt;
&lt;br /&gt;
Mainly developer for CM3D2 plug-ins. Some of my creations:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/denikson/CM3D2.MaidFiddler Maid Fiddler] (CM3D2 in-game editor)&lt;br /&gt;
* [https://github.com/denikson/CM3D2.YATranslator YATranslator] (a translation loader for CM3D2)&lt;br /&gt;
* Tutorials for ReiPatcher and UnityInjector&lt;br /&gt;
&lt;br /&gt;
== Contact ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/denikson denikson@GitHub] (my projects)&amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.hongfire.com/forum/member/1347954-denikson denikson@HongFire]&amp;lt;br&amp;gt;&lt;br /&gt;
ghorsington#0834 on Discord&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=User:Denikson&amp;diff=22763</id>
		<title>User:Denikson</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=User:Denikson&amp;diff=22763"/>
				<updated>2017-11-01T15:24:04Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= About denikson =&lt;br /&gt;
&lt;br /&gt;
Mainly developer for CM3D2 plug-ins. Some of my creations:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/denikson/CM3D2.MaidFiddler Maid Fiddler] (CM3D2 in-game editor)&lt;br /&gt;
* [https://github.com/denikson/CM3D2.YATranslator YATranslator] (a translation loader for CM3D2)&lt;br /&gt;
* Tutorials for ReiPatcher and UnityInjector&lt;br /&gt;
&lt;br /&gt;
== Contact ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/denikson denikson@GitHub] (my projects)&amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.hongfire.com/forum/member/1347954-denikson denikson@HongFire]&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Technical_Help&amp;diff=22762</id>
		<title>Custom Maid 3D2/Technical Help</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Technical_Help&amp;diff=22762"/>
				<updated>2017-11-01T15:23:12Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: Corrected some notes about YATranslator&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
=FAQ=&lt;br /&gt;
==Running the game==&lt;br /&gt;
*'''Q1: I keep getting an &amp;quot;(0) Yotogi.Category enum parse error (character not japanese)&amp;quot; error when I run the game and I have tried both AppLocale and NTLEA?'''&lt;br /&gt;
: A: You can't use AppLocale to run the x64 version because AppLocale don't support x64 version. but you can use AppLocale to run the x86 version on Windows 7,8 by step below&lt;br /&gt;
# Copy files and folders CM3D2x86_Data and CM3D2x86.exe from '''installation folder''' into your game folder. (example: C:\KISS\CM3D2\)&lt;br /&gt;
# Right click CM3D2x86.exe and select Run with Japanese locale. (you need [http://www.hongfire.com/forum/showthread.php/328830 HF pApploc] for the right-click options.)&amp;lt;br&amp;gt; '''''Note: HF pAppLoc doesn't work with Windows 10 or x64 version.'''''&lt;br /&gt;
: A: The best way for solve this problem is set '''window system locate to japanese''' but if you still want to run the x64 version or window 10 without set window system, you can using [https://ntlea.codeplex.com NTLEA x64] by setting [https://puu.sh/y0gTm/9619f6c611.png here] and press the arrow on the bottom right. This makes that you can right click CM3D2x64 to run with NTLEA x64.&lt;br /&gt;
: A: Set '''window system locate to japanese''' to do the following:&lt;br /&gt;
: Control Panel &amp;gt; Region &amp;gt; Administrative Tab &amp;gt; Language for non-Unicode programs choose &amp;lt;code&amp;gt;Japanese(Japan)&amp;lt;/code&amp;gt; and restart your computer.&lt;br /&gt;
&lt;br /&gt;
*'''Q2: My game crashes doing in maid creation or doing change skin color and my graphic card is AMD. How to fix this problem?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Maybe this guide is helpful for you [http://www.hongfire.com/forum/showthread.php/445139-AMD-CRASH-FIX-FOR-Radeon-HD-Series AMD CRASH FIX FOR Radeon HD Series] or you can access [http://pastebin.com/t3m1Lg3h this] in case the website blocked.&lt;br /&gt;
&lt;br /&gt;
*'''Q3: How do I install the translations?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: See [[Custom_Maid_3D_2/Technical_Help#Translate_Plus_Plugin|Translate Plus]] or [[Custom_Maid_3D_2/Technical_Help#YATranslator_Plugin|YATranslator]].&lt;br /&gt;
&lt;br /&gt;
*'''Q4: I get this error when running the HF Patch: &amp;quot;... The game is an unsupported version. This patch requires version 1.03...&amp;quot;, what can I do?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Install the official v1.03 patch and then run the HF Patch again.&lt;br /&gt;
&lt;br /&gt;
*'''Q5: I get a &amp;quot;Daily panel&amp;quot; error during gameplay.'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Make sure that you have the official 1.03 patch installed (and it is correct version x86 or x64) and then run the HF Patch again.&lt;br /&gt;
&lt;br /&gt;
*'''Q6: When installing patch keeps telling me &amp;quot;Game main executable couldn't be found, patch may be invalid&amp;quot; that after I try to install the patch.&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Make sure your game is installed correctly. If not installed correctly, patch cannot be detected CM3D2 in the window. If you make sure you have done this correctly, try reloading the patch again.&lt;br /&gt;
&lt;br /&gt;
*'''Q7: Incorrect Position UI, Transparent UI, White UI, Black screen stuck on Day 1, Night service skill name overlapping after update patch.'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Delete Folder &amp;quot;Assets&amp;quot; and &amp;quot;Texture&amp;quot; in &amp;lt;code&amp;gt;Sybaris\UnityInjector\Config&amp;lt;/code&amp;gt; and replace them with files download from [https://mega.nz/#!soIGDAAb!OPEppFIJNIJ-iG1m6yDr1HI9wCn9OhzCMuQhbQZNRV4 v1.49 UI translation]. This solve whatever problem you encouter (v1.49 UI translation for ver1.52, older version you can find them in HF).&lt;br /&gt;
: '''''Note: this trouble often found after KISS update the game, be careful this solution in this specific to your game version.'''''&lt;br /&gt;
&lt;br /&gt;
*'''Q8: After installed Karaoke Pack VR, I can't found the karaoke button on the menu and I have used translate plugin?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Update patch v1.53 and replace a file in translate UI assets folder with file from [http://www.hongfire.com/forum/forum/hentai-lair/hf-modding-translation/custom-maid-3d-2-mods/414082/page9#post5825775 here].&lt;br /&gt;
&lt;br /&gt;
==Gameplay==&lt;br /&gt;
*'''Q1: I got this option for my maid to choose between Free and something. What does this mean? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You are choosing between making your [[Custom_Maid_3D_2/Gameplay/The_Maid_Profile#Maid_Type|Maid Type]]. There are two types of maid is personal (only has sex with you) and free (has sex with the customers). The first earns you less money than the second.&lt;br /&gt;
&lt;br /&gt;
*'''Q2: How can I replay VIP scenes?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: &amp;lt;del&amp;gt;If you want to play them again, you must keep a save file before play the VIP. (After 100 days in game, VIP events that have been played over the first 99 days in game are again avalable to be played with forever but the same requirements are still applied as per the VIP event.)&amp;lt;/del&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
: A: After v1.21 and Plus Pack, you can replay unlocked VIP events in [[Custom_Maid_3D_2/Gameplay#Free_Mode|Free Mode]].&lt;br /&gt;
&lt;br /&gt;
*'''Q3: What are red options during sex?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: These are '''one-time''' options for the skill. You can use them again next time if you use this skill again.&lt;br /&gt;
&lt;br /&gt;
*'''Q4: How do I get more maids? I only have 1-2.'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You need to get your club '''out of debt''' first. Also, there is no upper limit on maids, but there is an upper limit on six working maids.&lt;br /&gt;
&lt;br /&gt;
*'''Q5: How do I unlock new rooms? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Increase your [[Custom_Maid_3D_2/Gameplay#Club_Grade|Club Grade]] from cleaning, decorating and eval and other [[Custom_Maid_3D_2/Gameplay#Rooms|Rooms]] require expansion installation. This is possible while still in debt.&lt;br /&gt;
&lt;br /&gt;
*'''Q6: After having sex with my maid, I got a notification. Something to do with being close? What does this mean? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: It means you've advanced your [[Custom_Maid_3D_2/Gameplay/The_Maid_Profile#Status|Relationship]] with your maid.&lt;br /&gt;
&lt;br /&gt;
*'''Q7: How do I earn CR for pay off the 10m Debt?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You can earn a small amount 50k~100k CR of money by &amp;quot;Dispatch&amp;quot; maids during the daytime, but the most amount of money comes from &amp;quot;Entertain&amp;quot; on nighttime. Entertain can earn 200k~1m CR per night per maid depending on club grade. Both Free Maids and Personal Maids are able to entertain.&lt;br /&gt;
&lt;br /&gt;
*'''Q8: It is said that I got &amp;quot;Ring&amp;quot; from the Lovers Trophy but I can't seem to find it... where can I find it?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: It's only unlocked by the time you got the &amp;quot;Lovers&amp;quot; Trophy. You still need to buy it from the shop for 10.000.000CR to equip the ring in the arms category.&lt;br /&gt;
&lt;br /&gt;
*'''Q9: All of sudden, There is no &amp;quot;Talk to her&amp;quot; option... What am I doing wrong? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You didn't put either top or bottom clothes for her, which makes her feels too embarrassed to talk to you. Try to put some clothes instead you ecchi-goshujinsama.&lt;br /&gt;
&lt;br /&gt;
*'''Q10: I can't seem to make the rental maid to do her VIP event? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You need to supervise her daily activities to earn her trust until you trigger all the 3 specific events which occurs per-day, the last one will pop-up a dialogue that tells you the VIP event is unlocked. The VIP event only occurs once and is not replayable since she's a rental maid. Explained in [[Custom_Maid_3D_2/Gameplay/VIP_Events#NPC_Maid|NPC Maid VIP]]&lt;br /&gt;
&lt;br /&gt;
*'''Q11: My game system don't have free mode, marriage, honeymoon, maid battle, empire league, vacation and karaoke, how can I unlock there systems? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You can unlock there game systems from installing append pack below.&lt;br /&gt;
#[http://kisskiss.tv/cm3d2/plus Plus Pack] will unlock '''free mode''' and '''maid battle''' system.&lt;br /&gt;
#[http://kisskiss.tv/cm3d2/plus2 Plus Pack ACT.2] will unlock '''marriage''' and '''empire league''' system.&lt;br /&gt;
#[http://kisskiss.tv/cm3d2/plus3 Plus Pack ACT.3] will unlock '''honeymoon''' system.&lt;br /&gt;
#[http://kisskiss.tv/cm3d2/vpvr Vacation Pack VR] will unlock '''vacation''' system.&lt;br /&gt;
#[http://kisskiss.tv/cm3d2/kpvr Karaoke Pack VR] will unlock '''karaoke''' system.&lt;br /&gt;
&lt;br /&gt;
==Text Hooking - Visual Novel Reader==&lt;br /&gt;
*'''Q1: Why can't I get VNR to work with the game?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: VNR doesn't work with the x64 version of the game, use the x86 version instead.&lt;br /&gt;
&lt;br /&gt;
*'''Q2: I managed to sync VNR to CM3D2 but I can't make it translate. The TL box won't come out. What's wrong?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Either enable the VNR built in hooker or rollback; overwrite your current VNR folder.&lt;br /&gt;
&lt;br /&gt;
=Installed Guide=&lt;br /&gt;
More information can be found in [http://www.hongfire.com/forum/forum/hentai-lair/hentai-game-discussion/418479 CM3D2 Hongfire] or [https://www.reddit.com/r/cm3d2/comments/6faqro/support_megathread CM3D2 Reddit].&lt;br /&gt;
==Installing the Game==&lt;br /&gt;
[[File:CM3D2_Installer.png|thumb|Click the highlighted button to install]]&lt;br /&gt;
[[File:CM3D2_Insert_disk2.png|thumb|Insert disk 2]]&lt;br /&gt;
#Set the '''window system locate to japanese''' or '''[https://ntlea.codeplex.com NTLEA x64]'''&amp;lt;br&amp;gt; '''''Note: HF pAppLoc doesn't work with Windows 10 or x64 version.'''''&lt;br /&gt;
#Extract &amp;lt;code&amp;gt;cm3d2_1.iso&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;cm3d2_2.iso&amp;lt;/code&amp;gt; '''(DO NOT extract the .mds files).'''&lt;br /&gt;
#Mount &amp;lt;code&amp;gt;cm3d2_1.iso&amp;lt;/code&amp;gt; with [http://www.disk-tools.com/download/daemon Daemontools Lite] (If you have trouble using other mounting software, Daemontools Lite has been confirmed to work).&lt;br /&gt;
#'''DO NOT autorun''', but open the mounted dvd in explorer and click &amp;lt;code&amp;gt;Installer.exe&amp;lt;/code&amp;gt; if your computer locale already in japanese, otherwise, right-click &amp;lt;code&amp;gt;Installer.exe&amp;lt;/code&amp;gt; and select Run with Japanese locale as an administrator (you need '''NTLEA x64''' for the right-click options).&lt;br /&gt;
#Optional: Change the install folder (default is C:\KISS).&lt;br /&gt;
#Click the button &amp;lt;code&amp;gt;インストール&amp;lt;/code&amp;gt; to start the CM3D2 setup.&lt;br /&gt;
#Confirm that you want to install to that location and wait while the setup until setup asks for disk 2.&lt;br /&gt;
#Mount &amp;lt;code&amp;gt;cm3d2_2.iso&amp;lt;/code&amp;gt; and click Retry.&lt;br /&gt;
#Wait for the setup to finish and close the installer.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Updating Patch==&lt;br /&gt;
[[File:Kissupdatepage.JPG|thumb|right|KISS official update webpage]]&lt;br /&gt;
[[File:Kissupdate folder.JPG|thumb|right|Extracted .zip files]]&lt;br /&gt;
#Set the '''window system locate to japanese''' or '''[https://ntlea.codeplex.com NTLEA x64]'''&amp;lt;br&amp;gt; '''''Note: HF pAppLoc doesn't work with Windows 10 or x64 version.'''''&lt;br /&gt;
#Download the latest full update that is meant for the version you run (either x86 or x64).&amp;lt;br&amp;gt; For lastes version update: http://kisskiss.tv/cm3d2/update.php&amp;lt;br&amp;gt; Or visit forum for mirrors: [http://www.hongfire.com/forum/forum/hentai-lair/hentai-game-discussion/418479 CM3D2 discussion]&lt;br /&gt;
#Download the updater ver.1.00～1.12 (cm3d2_up_for_1_00-1_12).&lt;br /&gt;
#Extract the .zip file and execute the &amp;lt;code&amp;gt;update.exe&amp;lt;/code&amp;gt; located inside the extracted folder. (It will auto-detect your installation directory) you can simply execute the &amp;lt;code&amp;gt;update.exe&amp;lt;/code&amp;gt; if your computer locale already in japanese, otherwise, right-click &amp;lt;code&amp;gt;update.exe&amp;lt;/code&amp;gt; and select ''Run with Japanese locale as an administrator'' (you need '''NTLEA x64''' for the right-click options).&lt;br /&gt;
#Choose &amp;lt;code&amp;gt;適用&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;開始&amp;lt;/code&amp;gt;, and wait for the patch to be extracted and installed.&lt;br /&gt;
#Download the latest updater (example: cm3d2_up153_x86_sub or cm3d2_up153_x64_sub) and repeat ''step 4 and 5'' after downloading the latest updater.&lt;br /&gt;
#After update complete, next time you can update the latest patch into your game without update ver.1.00～1.12 again.&lt;br /&gt;
Additional screenshots for '''Step 5''' as below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Kissupdate patch1.JPG|300px|center]] || [[File:Kissupdate patch2.JPG|300px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''''1st Note:''' If the patch didn't detect your installation directory and/or somehow the update.exe bugged, you can overwrite the ''GameData'' folder, and you will also need to update the ''update.lst'' file, which is advanced for veteran users.''&amp;lt;br&amp;gt;&lt;br /&gt;
'''''2nd Note:''' The '''update.exe''' will not install an already installed patches/DLCs as seen in additional screenshots for Step 5 where the START option is '''''greyed out''''', it follows the ''update.lst'' file, in case you are wondering it is located on your CM3D2 Root directory. (example: ''C:\KISS\CM3D2\'')''&amp;lt;br&amp;gt;&lt;br /&gt;
'''''3rd Note:''' For the old version update can be found [http://kisskiss.tv/cm3d2/oldupdate.php here]''&lt;br /&gt;
&lt;br /&gt;
==Installing Sybaris==&lt;br /&gt;
===Sybaris FAQ===&lt;br /&gt;
*'''Q1: What is Sybaris?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Sybaris is loader that runs plugins other than the official plugins have been installed in the base game.&lt;br /&gt;
&lt;br /&gt;
*'''Q2: What is the difference between Sybaris and Reipatcher?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Both loader have no difference in usability. The only difference is the methods of operation.&lt;br /&gt;
&lt;br /&gt;
*'''Q3: Why use Sybaris?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Sybaris have the advantage better than Reipatcher is:&amp;lt;br&amp;gt;&lt;br /&gt;
# Does not affect the base game, you can go back to vanilla anytime.&amp;lt;br&amp;gt;&lt;br /&gt;
# Updating the game causes less problems.&lt;br /&gt;
&lt;br /&gt;
*'''Q4: Sybaris have a disadvantage?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Sybaris has the following disadvantages:&amp;lt;br&amp;gt;&lt;br /&gt;
# Many plugins for Sybaris are only available in japanese language.&amp;lt;br&amp;gt;&lt;br /&gt;
# Some Reipatcher plugins are incompatible with Sybaris, such as Unified Translation Loader.&lt;br /&gt;
&lt;br /&gt;
*'''Q5: Sybaris need to install Reipatcher?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: No&lt;br /&gt;
&lt;br /&gt;
*'''Q6: How many sybaris plugins are supported?&lt;br /&gt;
: A: You can check [https://pastebin.com/va3qWhaQ here] or [http://motimoti3d.jp/blog-entry-37.html motimoti3d]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
===Sybaris===&lt;br /&gt;
For an easy installation you can download: [https://mega.nz/#!XFJUQAjL!G2GMTKUt2XGCo94Q3SII5Ki02u1LtMEECyCa9QrEr-g Sybaris Starter Pack 1.52] or [http://www.hongfire.com/forum/forum/hentai-lair/hf-modding-translation/custom-maid-3d-2-mods/5816208-sybaris-aio-ultimate-english-expansion-1-53-1-beta-suggestions-are-welcome Sybaris AIO Ultimate English Expansion - 1.53.1 Beta]&amp;lt;br&amp;gt;&lt;br /&gt;
This Package contains:&lt;br /&gt;
* Sybaris support v1.52+&lt;br /&gt;
* Plugins&lt;br /&gt;
* Translator&lt;br /&gt;
* Uncensor&lt;br /&gt;
&lt;br /&gt;
1. Download [https://ux.getuploader.com/cm3d2_e/download/317/cm3d2_e_317.zip Sybaris] or Sybaris Starter Pack or Sybaris AIO&amp;lt;br&amp;gt;&lt;br /&gt;
2. Copy '''opengl32.dll''' and '''Sybaris''' folder and place into the game folder. example: &amp;lt;code&amp;gt;C:\KISS\CM3D2&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Please use opengl32.dll according to version game you play.&amp;lt;br&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;cm3d2_e_317\opengl32.dll&amp;lt;/code&amp;gt; for the 64bit version (x64).&lt;br /&gt;
# &amp;lt;code&amp;gt;cm3d2_e_317\x86\opengl32.dll&amp;lt;/code&amp;gt; for the 32bit version (x86).&lt;br /&gt;
&amp;lt;code&amp;gt;SybarisArcEditor&amp;lt;/code&amp;gt; is optional if you need to install, copy and then put in game folder. This program will allow you to view and edit .arc files.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Basic Plugin===&lt;br /&gt;
1. Download [https://ux.getuploader.com/cm3d2_h/download/58/cm3d2_h_58.zip Basic Plugin] or Sybaris Starter Pack or Sybaris AIO&amp;lt;br&amp;gt;&lt;br /&gt;
This Package contains:&lt;br /&gt;
* MaidVoicePitch Plugin&lt;br /&gt;
* ExternalSaveData Plugin&lt;br /&gt;
* FastFade Plugin&lt;br /&gt;
* AddModsSlider Plugin&lt;br /&gt;
* ExternalPreset Plugin&lt;br /&gt;
* ConsistentWindowPosition Plugin '''(Optional)'''&lt;br /&gt;
* EditSceneUndo Plugin '''(Optional)'''&lt;br /&gt;
* LogWindow Plugin '''(Optional)'''&lt;br /&gt;
* PersonalizedEditSceneSettings Plugin '''(Optional)'''&lt;br /&gt;
* SkillCommandShortCut Plugin '''(Optional)'''&lt;br /&gt;
* VoiceNormalizer Plugin '''(Optional)'''&lt;br /&gt;
2. Copy .dll files in folder &amp;lt;code&amp;gt;Loader&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;UnityInjector&amp;lt;/code&amp;gt; from basic plugin to sybaris in game folder.&lt;br /&gt;
# &amp;lt;code&amp;gt;cm3d2_h_58\ReiPatcherレス化プラグイン一式170606\Sybaris\Loader&amp;lt;/code&amp;gt; ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Loader&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;cm3d2_h_58\ReiPatcherレス化プラグイン一式170606\Sybaris\Plugins\Unityinjector&amp;lt;/code&amp;gt; ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
3. Copy files in folder &amp;lt;code&amp;gt;Config&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\UnityInjector\Config&amp;lt;/code&amp;gt; in game folder.&amp;lt;br&amp;gt;&lt;br /&gt;
4. For '''optional''' plugins, you can install them by copy .dll files in &amp;lt;code&amp;gt;Sybaris\Loader\オプション&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\オプション&amp;lt;/code&amp;gt; from basic plugin into Sybaris in game folder.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''1st Note:''' '''FastFade Plugin''' will change the display of the game. If you don't need to use the plugin, then shouldn't be installed.''&amp;lt;br&amp;gt;&lt;br /&gt;
'''''2nd Note:''' Other plugins mostly there is step to installation same as basic plugin. However, for correct let check the readme before installation.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===TranslatePlus Plugin===&lt;br /&gt;
'''*TranslationPlus is known to have compatibility issues with v1.49 or newer with translate textures and skill icons. Consider using [[Custom_Maid_3D_2/Technical_Help#YATranslator_Plugin|YATranslator]] or proceed at your own risk.&amp;lt;br&amp;gt;'''&lt;br /&gt;
1. Download [https://github.com/zklm/CM3D2.TranslationPlus/releases Translate Plus Plugin] or Sybaris Starter Pack&amp;lt;br&amp;gt;&lt;br /&gt;
2. Copy files below in the translateplus folder to these folders.&lt;br /&gt;
# CM3D2.TranslationPlus.Sybaris.Patcher.dll ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Loader&amp;lt;/code&amp;gt;&lt;br /&gt;
# CM3D2.TranslationPlus.Hook ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
# CM3D2.TranslationPlus.Plugin ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
3. TranslatePlus Plugin is require a translate data to run with the plugin. you can find translate data in '''Sybaris Starter''' or '''Sybaris AIO''', then put a translate data into &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config&amp;lt;/code&amp;gt;&lt;br /&gt;
# Place translate data from &amp;quot;Assets&amp;quot; folder in &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config\Assets&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Place translate data from &amp;quot;String&amp;quot; folder in &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config\Strings&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Place translate data from &amp;quot;Texture&amp;quot; folder in &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config\Texture&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===YATranslator Plugin===&lt;br /&gt;
YATranslator is a translation loader. It supports CM3D2 v1.49 and newer, works with ReiPatcher and Sybaris, and replaces TranslationPlus or Unified Translation Loader. The plug-in also fixes many loading errors present in other translation loaders. &amp;lt;br&amp;gt;&lt;br /&gt;
1. Download [https://github.com/denikson/CM3D2.YATranslator/releases YATranslator Plugin] or [http://www.hongfire.com/forum/forum/hentai-lair/hf-modding-translation/custom-maid-3d-2-mods/5816208-sybaris-aio-ultimate-english-expansion-1-53-1-beta-suggestions-are-welcome Sybaris AIO] &amp;lt;br&amp;gt;&lt;br /&gt;
2. '''Remove TranslationPlus or Unified Translation Loader'''&amp;lt;br&amp;gt;&lt;br /&gt;
3. Follow the installation guides [https://github.com/denikson/CM3D2.YATranslator/wiki/Installation here] or in the READMEs&amp;lt;br&amp;gt;&lt;br /&gt;
4. YATranslator Plugin is require a translate data to run with the plugin. you can find translate data in '''Sybaris Starter''' or '''Sybaris AIO''', then put a translate data into &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config&amp;lt;/code&amp;gt;&lt;br /&gt;
# Place translate data from &amp;quot;Assets&amp;quot; folder in &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config\Assets&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Place translate data from &amp;quot;String&amp;quot; folder in &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config\Strings&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Place translate data from &amp;quot;Texture&amp;quot; folder in &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config\Texture&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''''1st Note:''' If you have any trouble with incorrect UI, transparent UI, white UI, black screen stuck on Day 1 or night service skill name overlapping, '''remove all previous translations loaders!''' The issues have been fixed in YATranslator, but having older translations loaders (TranslationPlus, UTL) conflict with the new plug-in. ''&amp;lt;br&amp;gt;&lt;br /&gt;
'''''2nd Note:''' It is recommended to get the '''AutoTranslate Plugin''' to enable automatic Google translations. You can find the plug-in on [http://www.hongfire.com/forum/forum/hentai-lair/hf-modding-translation/custom-maid-3d-2-mods/5756478-plugin-automatic-google-translate-v1-3-2-2017-10-26 HongFire] and [https://github.com/texel-sensei/CM3D2.AutoTranslate/releases GitHub]''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===YASDPlus Plugin===&lt;br /&gt;
'''First Step: Prepare File'''&amp;lt;br&amp;gt;&lt;br /&gt;
1. Download [https://mega.nz/#!G8Y3gIwL!6U5x1xWj-QzmP8CULD6OoaxuvbWJhR1SUlcKpx_aMtI Soft-Demosaic Plugin] (Password: byreisen)&amp;lt;br&amp;gt;&lt;br /&gt;
Copy file '''CM3D2.NoMosaic.Plugin.dll''' from the CM3D2.NoMosaic folder to &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\UnityInjector&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
2. Next Step (If you have Sybaris Starter Pack or Sybaris AIO, skip to step 2.3)&amp;lt;br&amp;gt;&lt;br /&gt;
Download [https://mega.nz/#!Y5hCXThS!jgbR9IFpBgFlT9V1-YEh9FpJK4ajoVweN9GOyTL5wrE Female Uncensor-Menelol(R4)] (Password: 4HF)&amp;lt;br&amp;gt;&lt;br /&gt;
Download [http://ux.getuploader.com/cm3d2_d/download/84/cm3d2_d_84.zip 適当ツールまとめ] &amp;lt;br&amp;gt;&lt;br /&gt;
# Go to folder &amp;lt;code&amp;gt;Girl Uncensor\UnityInjector\config&amp;lt;/code&amp;gt; of Female Uncensor-Menelol, find all .png file inside the folder.&amp;lt;br&amp;gt;&lt;br /&gt;
# Import .png files in Female Uncensor-Menelol folder to program '''[CM3D2]tex←→png変換.exe''' in &amp;lt;code&amp;gt;cm3d2_d_84\[CM3D2]適当ツールまとめ&amp;lt;/code&amp;gt; then convert .png to .tex, doing all the files until complete.&amp;lt;br&amp;gt;&lt;br /&gt;
# Go to folder &amp;lt;code&amp;gt;CM3D2\Sybaris\GameData&amp;lt;/code&amp;gt;, create a new folder &amp;quot;FemaleUncensor&amp;quot; then pull all .tex uncensor files from converts into this folder.&amp;lt;br&amp;gt;&lt;br /&gt;
You can skip this step, If you don't need to male uncensor. but If you need to do the following:&amp;lt;br&amp;gt;&lt;br /&gt;
3. Download [http://ux.getuploader.com/cm3d2_d/download/24/cm3d2_d_24.zip ManTNP] or Sybaris Starter Pack or Sybaris AIO&amp;lt;br&amp;gt;&lt;br /&gt;
Then put male uncensor into &amp;lt;code&amp;gt;CM3D2\Sybaris\GameData&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Second Step: Installation'''&amp;lt;br&amp;gt;&lt;br /&gt;
1. Download [http://pastebin.com/pTKGk0Ef YASDPlus Plugin] or Sybaris Starter Pack or Sybaris AIO&amp;lt;br&amp;gt;&lt;br /&gt;
2. Copy file '''cm3d2.yasdplus.plugin.cs''' into folder &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\AutoCompile&amp;lt;/code&amp;gt;. when opening the game, the game will generate this files below&lt;br /&gt;
# cm3d2.yasdplus.plugin.dll in &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
# yasd.ini in &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config&amp;lt;/code&amp;gt;&lt;br /&gt;
When you get the above files, YASDPlus Plugin installation have been completed.&amp;lt;br&amp;gt;&lt;br /&gt;
''Note: You can setting uncensor in the game by opening '''yasd.ini''' file in Notepad. See the setting from [http://motimoti3d.jp/blog-entry-53.html here].''&amp;lt;br&amp;gt;&lt;br /&gt;
''Note: If male character has cylinder penis, because '''you do not put the male uncensor''' into sybaris. Please see third step in the first step: prepare file.''&lt;br /&gt;
&lt;br /&gt;
==Installing Mod==&lt;br /&gt;
[[File:Cm3d2installmod01.jpg|thumb|right|Example installing mods within folder]]&lt;br /&gt;
Installation the mod, you can follow the steps below.&amp;lt;br&amp;gt;&lt;br /&gt;
'''For Vanilla'''&amp;lt;br&amp;gt;&lt;br /&gt;
1. Go to game folder create a new folder &amp;quot;Mod&amp;quot; (example: C:\KISS\CM3D2\Mod)&amp;lt;br&amp;gt;&lt;br /&gt;
2. Put the mod files into &amp;lt;code&amp;gt;CM3D2\Mod&amp;lt;/code&amp;gt; folder.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''For Sybaris'''&amp;lt;br&amp;gt;&lt;br /&gt;
1. Go to &amp;lt;code&amp;gt;CM3D2\Sybaris\GameData&amp;lt;/code&amp;gt; in sybaris folder.&amp;lt;br&amp;gt;&lt;br /&gt;
2. Put the mod files into &amp;lt;code&amp;gt;CM3D2\Sybaris\GameData&amp;lt;/code&amp;gt; folder.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Note: Some mod must be placed in sybaris folder, please check the readme before installing.''&amp;lt;br&amp;gt;&lt;br /&gt;
''Note: For .mod file should be placed without the folder.''&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=User:Denikson&amp;diff=22761</id>
		<title>User:Denikson</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=User:Denikson&amp;diff=22761"/>
				<updated>2017-11-01T15:16:16Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: Created page with &amp;quot;= About denikson =  Mainly developer for CM3D2 plug-ins. Some of my creations:  * [https://github.com/denikson/CM3D2.MaidFiddler Maid Fiddler] (CM3D2 in-game editor) * [https:...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= About denikson =&lt;br /&gt;
&lt;br /&gt;
Mainly developer for CM3D2 plug-ins. Some of my creations:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/denikson/CM3D2.MaidFiddler Maid Fiddler] (CM3D2 in-game editor)&lt;br /&gt;
* [https://github.com/denikson/CM3D2.YATranslator YATranslator] (a translation loader for CM3D2)&lt;br /&gt;
* Tutorials for ReiPatcher and UnityInjector&lt;br /&gt;
&lt;br /&gt;
== Contact ==&lt;br /&gt;
&lt;br /&gt;
[https://github.com/denikson denikson@GitHub] (my projects)&lt;br /&gt;
[http://www.hongfire.com/forum/member/1347954-denikson denikson@HongFire]&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Technical_Help&amp;diff=22626</id>
		<title>Custom Maid 3D2/Technical Help</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Technical_Help&amp;diff=22626"/>
				<updated>2017-09-11T20:18:52Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
=FAQ=&lt;br /&gt;
==Running the game==&lt;br /&gt;
*'''Q: I keep getting an &amp;quot;(0) Yotogi.Category enum parse error (character not japanese)&amp;quot; error when I run the game and I have tried both AppLocale and NTLEA?'''&lt;br /&gt;
: A: You can't use AppLocale to run the x64 version because AppLocale don't support x64 version. but you can use AppLocale to run the x86 version on Windows 7,8 by step below&lt;br /&gt;
# Copy files and folders CM3D2x86_Data and CM3D2x86.exe from installation folder into your game folder. (example: C:\KISS\CM3D2\)&lt;br /&gt;
# Right-click CM3D2x86.exe and select Run with Japanese locale. (you need [http://www.hongfire.com/forum/showthread.php/328830 HF pApploc] for the right-click options.)&amp;lt;br&amp;gt; '''''Note: HF pAppLoc doesn't work with Windows 10 or x64 version.'''''&lt;br /&gt;
: A: The best way for solve this problem is set '''window system locate to japanese''' but if you still want to run the x64 version or window 10 without set window system, you can try this [http://www.hongfire.com/forum/showthread.php/444096-KISS-Custom-Maid-3D-2-%28%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%A1%E3%82%A4%E3%83%893D2%29-Discussion-FAQ?p=3706481#post3706481 solution], which is using NTLEA x64.&lt;br /&gt;
&lt;br /&gt;
*'''Q: My game crashes doing in maid creation or doing change skin color and my graphic card is AMD. How to fix this problem?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Maybe this guide is helpful for you [http://www.hongfire.com/forum/showthread.php/445139-AMD-CRASH-FIX-FOR-Radeon-HD-Series AMD CRASH FIX FOR Radeon HD Series] or you can access [http://pastebin.com/t3m1Lg3h this] in case the website blocked.&lt;br /&gt;
&lt;br /&gt;
*'''Q: How do I install the translations?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: See [[Custom_Maid_3D_2/Technical_Help#Translate_Plus_Plugin|Translate Plus]] or [[Custom_Maid_3D_2/Technical_Help#YATranslator_Plugin|YATranslator]].&lt;br /&gt;
&lt;br /&gt;
*'''Q: I get this error when running the HF Patch: &amp;quot;... The game is an unsupported version. This patch requires version 1.03...&amp;quot;, what can I do?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Install the official 1.03 patch and then run the [[#The HF Patch|Custom Maid 3D 2 HF Patch]] again. There are mirrors to the official patch in the [http://www.hongfire.com/forum/showthread.php/444096 CM3D2 discussion].&lt;br /&gt;
&lt;br /&gt;
*'''Q: I get a &amp;quot;Daily panel&amp;quot; error during gameplay.'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Make sure that you have the official 1.03 patch installed (and it is correct version - x86 or x64) and then run the [[#The HF Patch|Custom Maid 3D 2 HF Patch]] again. There are mirrors to the official patch in the [http://www.hongfire.com/forum/showthread.php/444096 CM3D2 discussion].&lt;br /&gt;
&lt;br /&gt;
*'''Q: It keeps telling me that the &amp;quot;game main executable couldn't be found, path maybe invalid and it says that after I try to install the patch.&amp;lt;br&amp;gt;&lt;br /&gt;
: A:&lt;br /&gt;
&lt;br /&gt;
*'''Q: Incorrect Position UI, Transparent UI, White UI, Black screen stuck on Day 1, Night service skill name overlapping after update patch.'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Delete Folder &amp;quot;Assets&amp;quot; and &amp;quot;Texture&amp;quot; in &amp;lt;code&amp;gt;Sybaris\UnityInjector\Config&amp;lt;/code&amp;gt; and replace them with files download from [http://goo.gl/6CsKNi v1.49 UI translation]. This solve whatever problem you encouter (v1.49 UI translation for v1.52, older version you can find them in HF).&lt;br /&gt;
: '''''Note: this trouble often found after KISS update the game, be careful this solution in this specific to your game version.'''''&lt;br /&gt;
&lt;br /&gt;
==Gameplay==&lt;br /&gt;
*'''Q: I got this option for my maid to choose between Free and something. What does this mean? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You are choosing between making your [[Custom_Maid_3D_2/Gameplay/The_Maid_Profile#Maid_Type|Maid Type]]. There are two types of maid is personal (only has sex with you) and free (has sex with the customers). The first earns you less money than the second.&lt;br /&gt;
&lt;br /&gt;
*'''Q: How can I replay VIP scenes?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: &amp;lt;del&amp;gt;If you want to play them again, you must keep a save file before play the VIP. (After 100 days in game, VIP events that have been played over the first 99 days in game are again avalable to be played with forever but the same requirements are still applied as per the VIP event.)&amp;lt;/del&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
: A: After v1.21 and Plus Pack, you can replay unlocked VIP events in [[Custom_Maid_3D_2/Gameplay#Free_Mode|Free Mode]].&lt;br /&gt;
&lt;br /&gt;
*'''Q: What are red options during sex?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: These are '''one-time''' options for the skill. You can use them again next time if you use this skill again.&lt;br /&gt;
&lt;br /&gt;
*'''Q: How do I get more maids? I only have 1-2.'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You need to get your club '''out of debt''' first. Also, there is no upper limit on maids, but there is an upper limit on six working maids.&lt;br /&gt;
&lt;br /&gt;
*'''Q: How do I unlock new rooms? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Increase your [[Custom_Maid_3D_2/Gameplay#Club_Grade|Club Grade]] from cleaning, decorating and eval and other [[Custom_Maid_3D_2/Gameplay#Rooms|Rooms]] require expansion installation. This is possible while still in debt.&lt;br /&gt;
&lt;br /&gt;
*'''Q: After having sex with my maid, I got a notification. Something to do with being close? What does this mean? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: It means you've advanced your [[Custom_Maid_3D_2/Gameplay/The_Maid_Profile#Status|Relationship]] with your maid.&lt;br /&gt;
&lt;br /&gt;
*'''Q: How do I earn CR for pay off the 10m Debt?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You can earn a small amount 50k~100k CR of money by &amp;quot;Dispatch&amp;quot; maids during the daytime, but the most amount of money comes from &amp;quot;Entertain&amp;quot; on nighttime. Entertain can earn 200k~1m CR per night per maid depending on club grade. Both Free Maids and Personal Maids are able to entertain.&lt;br /&gt;
&lt;br /&gt;
*'''Q: It is said that I got &amp;quot;Ring&amp;quot; from the Lovers Trophy but I can't seem to find it... where can I find it?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: It's only unlocked by the time you got the &amp;quot;Lovers&amp;quot; Trophy. You still need to buy it from the shop for 10.000.000CR to equip the ring in the arms category.&lt;br /&gt;
&lt;br /&gt;
*'''Q: All of sudden, There is no &amp;quot;Talk to her&amp;quot; option... What am I doing wrong? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You didn't put either top or bottom clothes for her, which makes her feels too embarrassed to talk to you. Try to put some clothes instead you ecchi-goshujinsama.&lt;br /&gt;
&lt;br /&gt;
*'''Q: I can't seem to make the rental maid to do her VIP event? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You need to supervise her daily activities to earn her trust until you trigger all the 3 specific events which occurs per-day, the last one will pop-up a dialogue that tells you the VIP event is unlocked. The VIP event only occurs once and is not replayable since she's a rental maid. Explained in [[Custom_Maid_3D_2/Gameplay/VIP_Events#NPC_Maid|NPC Maid VIP]]&lt;br /&gt;
&lt;br /&gt;
==Text Hooking - Visual Novel Reader==&lt;br /&gt;
*'''Q: Why can't I get VNR to work with the game?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: VNR doesn't work with the x64 version of the game, use the x86 version instead.&lt;br /&gt;
&lt;br /&gt;
*'''Q: I managed to sync VNR to CM3D2 v1.03 but I can't make it translate. The TL box won't come out. What's wrong?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Either enable the VNR built in hooker or rollback; overwrite your current VNR folder.&lt;br /&gt;
&lt;br /&gt;
=Installed Guide=&lt;br /&gt;
More information can be found in [http://www.hongfire.com/forum/forum/hentai-lair/hentai-game-discussion/418479 CM3D2 Hongfire] or [https://www.reddit.com/r/cm3d2/comments/6faqro/support_megathread CM3D2 Reddit].&lt;br /&gt;
==Installing the Game==&lt;br /&gt;
[[File:CM3D2_Installer.png|thumb|Click the highlighted button to install]]&lt;br /&gt;
[[File:CM3D2_Insert_disk2.png|thumb|Insert disk 2]]&lt;br /&gt;
#Set the '''window system locate to japanese''' or download [http://www.hongfire.com/forum/showthread.php/328830 HF pApploc]&amp;lt;br&amp;gt; '''''Note: HF pAppLoc doesn't work with Windows 10 or x64 version.'''''&lt;br /&gt;
#Extract &amp;lt;code&amp;gt;cm3d2_1.iso&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;cm3d2_2.iso&amp;lt;/code&amp;gt; '''(DO NOT extract the .mds files)'''&lt;br /&gt;
#Mount &amp;lt;code&amp;gt;cm3d2_1.iso&amp;lt;/code&amp;gt; with [http://www.disk-tools.com/download/daemon Daemontools Lite] (If you have trouble using other mounting software, Daemontools Lite has been confirmed to work)&lt;br /&gt;
#'''DO NOT autorun''', but open the mounted dvd in explorer and click &amp;lt;code&amp;gt;Installer.exe&amp;lt;/code&amp;gt; if your computer locale already in japanese, otherwise, right-click &amp;lt;code&amp;gt;Installer.exe&amp;lt;/code&amp;gt; and select Run with Japanese locale as an administrator (you need [http://www.hongfire.com/forum/showthread.php/328830 HF pApploc] for the right-click options)&lt;br /&gt;
#Optional: Change the install folder (default is C:\KISS).&lt;br /&gt;
#Click the button &amp;lt;code&amp;gt;インストール&amp;lt;/code&amp;gt; to start the CM3D2 setup.&lt;br /&gt;
#Confirm that you want to install to that location and wait while the setup until setup asks for disk 2.&lt;br /&gt;
#Mount &amp;lt;code&amp;gt;cm3d2_2.iso&amp;lt;/code&amp;gt; and click Retry.&lt;br /&gt;
#Wait for the setup to finish and close the installer.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Updating Patch==&lt;br /&gt;
[[File:Kissupdatepage.JPG|thumb|right|KISS official update webpage]]&lt;br /&gt;
[[File:Kissupdate folder.JPG|thumb|right|Extracted .zip files]]&lt;br /&gt;
#Set the '''window system locate to japanese''' or download [http://www.hongfire.com/forum/showthread.php/328830 HF pApploc]&amp;lt;br&amp;gt; '''''Note: HF pAppLoc doesn't work with Windows 10 or x64 version.'''''&lt;br /&gt;
#Download the latest full update that is meant for the version you run (either x86 or x64).&amp;lt;br&amp;gt; For lastes update patch: http://kisskiss.tv/cm3d2/update.php&amp;lt;br&amp;gt; For old update patch: http://kisskiss.tv/cm3d2/oldupdate.php&amp;lt;br&amp;gt; Or visit forum  for mirrors update patch: [http://www.hongfire.com/forum/forum/hentai-lair/hentai-game-discussion/418479 CM3D2 discussion].&lt;br /&gt;
#Download the updater ver.1.00～1.12 (cm3d2_up_for_1_00-1_12)&lt;br /&gt;
#Extract the .zip file and execute the &amp;lt;code&amp;gt;update.exe&amp;lt;/code&amp;gt; located inside the extracted folder. (It will auto-detect your installation directory) you can simply execute the &amp;lt;code&amp;gt;update.exe&amp;lt;/code&amp;gt; if your computer locale already in japanese, otherwise, right-click &amp;lt;code&amp;gt;update.exe&amp;lt;/code&amp;gt; and select ''Run with Japanese locale as an administrator'' (you need [http://www.hongfire.com/forum/showthread.php/328830 HF pApploc] for the right-click options).&lt;br /&gt;
#Choose &amp;lt;code&amp;gt;適用&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;開始&amp;lt;/code&amp;gt;, and wait for the patch to be extracted and installed.&lt;br /&gt;
#Download the latest updater (example: cm3d2_up148_x86_sub or cm3d2_up148_x64_sub) and repeat ''step 4 and 5'' after downloading the latest updater.&lt;br /&gt;
#After update complete, next time you can update the latest patch into your game without update ver.1.00～1.12 again.&lt;br /&gt;
Additional screenshots for '''Step 5''' as below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Kissupdate patch1.JPG|300px|center]] || [[File:Kissupdate patch2.JPG|300px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''''1st Note:''' If the patch didn't detect your installation directory and/or somehow the update.exe bugged, you can overwrite the ''GameData'' folder, and you will also need to update the ''update.lst'' file, which is advanced for veteran users.''&lt;br /&gt;
&lt;br /&gt;
'''''2nd Note:''' The '''update.exe''' will not install an already installed patches/DLCs as seen in additional screenshots for Step 5 where the START option is '''''greyed out''''', it follows the ''update.lst'' file, in case you are wondering it is located on your CM3D2 Root directory. (example: ''C:\KISS\CM3D2\'')''&lt;br /&gt;
&lt;br /&gt;
==Installing Sybaris==&lt;br /&gt;
===Sybaris FAQ===&lt;br /&gt;
*'''Q: What is Sybaris?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Sybaris is loader that runs plugins other than the official plugins have been installed in the base game.&lt;br /&gt;
&lt;br /&gt;
*'''Q: What is the difference between Sybaris and Reipatcher?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Both loader have no difference in usability. The only difference is the methods of operation.&lt;br /&gt;
&lt;br /&gt;
*'''Q: Why use Sybaris?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Sybaris have the advantage better than Reipatcher is:&amp;lt;br&amp;gt;&lt;br /&gt;
# Does not affect the base game, you can go back to vanilla anytime.&amp;lt;br&amp;gt;&lt;br /&gt;
# Updating the game causes less problems.&lt;br /&gt;
&lt;br /&gt;
*'''Q: Sybaris have a disadvantage?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Sybaris has the following disadvantages:&amp;lt;br&amp;gt;&lt;br /&gt;
# Many plugins for Sybaris are only available in japanese language.&amp;lt;br&amp;gt;&lt;br /&gt;
# Some Reipatcher plugins are incompatible with Sybaris, such as Unified Translation Loader.&lt;br /&gt;
&lt;br /&gt;
*'''Q: Sybaris need to install Reipatcher?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: No&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
===Sybaris===&lt;br /&gt;
For an easy installation you can download: [https://mega.nz/#!XFJUQAjL!G2GMTKUt2XGCo94Q3SII5Ki02u1LtMEECyCa9QrEr-g Sybaris Starter Pack 1.52] or [http://www.hongfire.com/forum/forum/hentai-lair/hf-modding-translation/custom-maid-3d-2-mods/5816208-sybaris-aio-ultimate-english-expansion-1-52-2-1-beta-suggestions-are-welcome Sybaris AIO Ultimate English Expansion 1.52.2.4 Beta]&amp;lt;br&amp;gt;&lt;br /&gt;
This Package contains:&lt;br /&gt;
* Sybaris support v1.52+&lt;br /&gt;
* Plugins&lt;br /&gt;
* Translator&lt;br /&gt;
* Uncensor&lt;br /&gt;
&lt;br /&gt;
1. Download [https://ux.getuploader.com/cm3d2_e/download/317/cm3d2_e_317.zip Sybaris] or Sybaris Starter Pack&amp;lt;br&amp;gt;&lt;br /&gt;
2. Copy '''opengl32.dll''' and '''Sybaris''' folder into the game folder. example: &amp;lt;code&amp;gt;C:\KISS\CM3D2&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Please use opengl32.dll according to version game you play.&amp;lt;br&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;cm3d2_e_317\opengl32.dll&amp;lt;/code&amp;gt; for the 64bit version (x64).&lt;br /&gt;
# &amp;lt;code&amp;gt;cm3d2_e_317\x86\opengl32.dll&amp;lt;/code&amp;gt; for the 32bit version (x86).&lt;br /&gt;
&amp;lt;code&amp;gt;SybarisArcEditor&amp;lt;/code&amp;gt; is optional. This program will allow you to view and edit .arc files.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Basic Plugin===&lt;br /&gt;
1. Download [https://ux.getuploader.com/cm3d2_h/download/58/cm3d2_h_58.zip Basic Plugin] or Sybaris Starter Pack&amp;lt;br&amp;gt;&lt;br /&gt;
This Package contains:&lt;br /&gt;
* MaidVoicePitch Plugin&lt;br /&gt;
* ExternalSaveData Plugin&lt;br /&gt;
* FastFade Plugin&lt;br /&gt;
* AddModsSlider Plugin&lt;br /&gt;
* ExternalPreset Plugin&lt;br /&gt;
* ConsistentWindowPosition Plugin '''(Optional)'''&lt;br /&gt;
* EditSceneUndo Plugin '''(Optional)'''&lt;br /&gt;
* LogWindow Plugin '''(Optional)'''&lt;br /&gt;
* PersonalizedEditSceneSettings Plugin '''(Optional)'''&lt;br /&gt;
* SkillCommandShortCut Plugin '''(Optional)'''&lt;br /&gt;
* VoiceNormalizer Plugin '''(Optional)'''&lt;br /&gt;
2. Copy .dll files in folder &amp;lt;code&amp;gt;Loader&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Plugins\UnityInjector&amp;lt;/code&amp;gt; from basic plugin to sybaris in game folder.&lt;br /&gt;
# &amp;lt;code&amp;gt;cm3d2_h_58\ReiPatcherレス化プラグイン一式170606\Sybaris\Loader&amp;lt;/code&amp;gt; ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Loader&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;cm3d2_h_58\ReiPatcherレス化プラグイン一式170606\Sybaris\Plugins\Unityinjector&amp;lt;/code&amp;gt; ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
3. Copy files in folder &amp;lt;code&amp;gt;Plugins\UnityInjector\Config&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\UnityInjector\Config&amp;lt;/code&amp;gt; in game folder.&amp;lt;br&amp;gt;&lt;br /&gt;
4. For '''optional''' plugins, you can install them by copy .dll files in &amp;lt;code&amp;gt;Sybaris\Loader\オプション&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\オプション&amp;lt;/code&amp;gt; from basic plugin into Sybaris in game folder.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Note: '''FastFade Plugin''' will change the display of the game. If you don't need to use the plugin, then shouldn't be installed.''&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Translate Plus Plugin===&lt;br /&gt;
{{msgbox&lt;br /&gt;
|border=#ddd&lt;br /&gt;
|background=#ddd&lt;br /&gt;
|textcolor=#000&lt;br /&gt;
|message='''NOTE:''' TranslationPlus is known to have compatibility issues with CM3D2 1.49 or newer with some translation files (especially textures and skill icons). Consider using [[Custom_Maid_3D_2/Technical_Help#YATranslator_Plugin|YATranslator]] or proceed at your own risk.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
1. Download [https://github.com/zklm/CM3D2.TranslationPlus/releases Translate Plus Plugin] or Sybaris Starter Pack&amp;lt;br&amp;gt;&lt;br /&gt;
2. Copy files below in the translate plus folder to these folders.&lt;br /&gt;
# CM3D2.TranslationPlus.Sybaris.Patcher.dll ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Loader&amp;lt;/code&amp;gt;&lt;br /&gt;
# CM3D2.TranslationPlus.Hook ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
# CM3D2.TranslationPlus.Plugin ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
3. Translate Plus Plugin is require a translate data to run with the plugin. you can find translate data in [http://www.hongfire.com/forum/forum/hentai-lair/hf-modding-translation/custom-maid-3d-2-mods/5678372-cm3d2-system-text-translation HF] or [https://mega.nz/#!XFJUQAjL!G2GMTKUt2XGCo94Q3SII5Ki02u1LtMEECyCa9QrEr-g Sybaris Starter Pack], then put a translate file into &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config&amp;lt;/code&amp;gt; (for system text translate, go to step 2)&lt;br /&gt;
# Create a new folder &amp;quot;Assets&amp;quot; and put translate files into &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config\Assets&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Create a new folder &amp;quot;String&amp;quot; and put translate files into &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config\Strings&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Create a new folder &amp;quot;Texture&amp;quot; and put translate files into &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config\Texture&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===YATranslator Plugin===&lt;br /&gt;
YATranslator is a translation loader. It supports CM3D2 1.49 and newer, works with ReiPatcher and Sybaris, and replaces TranslationPlus and the Unified Translation Plugin.&lt;br /&gt;
&lt;br /&gt;
1. Download [https://github.com/denikson/CM3D2.YATranslator/releases YATranslator Plugin] or [http://www.hongfire.com/forum/forum/hentai-lair/hf-modding-translation/custom-maid-3d-2-mods/5816208-sybaris-aio-ultimate-english-expansion-1-52-2-1-beta-suggestions-are-welcome Sybaris AIO Ultimate English Expansion 1.52.2.4 Beta] &amp;lt;br&amp;gt;&lt;br /&gt;
2. '''Remove TranslationPlus or the Unified Translation Loader'''&amp;lt;br&amp;gt;&lt;br /&gt;
3. Follow the installation guides included in the READMEs&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====AutoTranslate====&lt;br /&gt;
Currently YATranslator a custom-fixed AutoTranslate Plugin to enable automatic Google translations.&lt;br /&gt;
You can find the latest version on [http://www.hongfire.com/forum/forum/hentai-lair/hf-modding-translation/custom-maid-3d-2-mods/5813782-plugin-yat-yet-another-translator-1-3-0-0-vpvr-subtitles-autotranslate?p=5814818#post5814818 HongFire].&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===YASDPlus Plugin===&lt;br /&gt;
'''First Step: Prepare File'''&amp;lt;br&amp;gt;&lt;br /&gt;
1. Download [https://mega.nz/#!G8Y3gIwL!6U5x1xWj-QzmP8CULD6OoaxuvbWJhR1SUlcKpx_aMtI Soft-Demosaic Plugin] (Password: byreisen)&amp;lt;br&amp;gt;&lt;br /&gt;
Copy file '''CM3D2.NoMosaic.Plugin.dll''' from the CM3D2.NoMosaic folder to &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\UnityInjector&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
2. Next Step (If you have Sybaris Starter Pack, skip to step 2.3)&amp;lt;br&amp;gt;&lt;br /&gt;
Download [https://mega.nz/#!Y5hCXThS!jgbR9IFpBgFlT9V1-YEh9FpJK4ajoVweN9GOyTL5wrE Female Uncensor-Menelol(R4)] (Password: 4HF)&amp;lt;br&amp;gt;&lt;br /&gt;
Download [http://ux.getuploader.com/cm3d2_d/download/84/cm3d2_d_84.zip 適当ツールまとめ] &amp;lt;br&amp;gt;&lt;br /&gt;
# Go to folder &amp;lt;code&amp;gt;Girl Uncensor\UnityInjector\config&amp;lt;/code&amp;gt; of Female Uncensor-Menelol, find all .png file inside the folder.&amp;lt;br&amp;gt;&lt;br /&gt;
# Import .png files in Female Uncensor-Menelol folder to program '''[CM3D2]tex←→png変換.exe''' in &amp;lt;code&amp;gt;cm3d2_d_84\[CM3D2]適当ツールまとめ&amp;lt;/code&amp;gt; then convert .png to .tex, doing all the files until complete.&amp;lt;br&amp;gt;&lt;br /&gt;
# Go to folder &amp;lt;code&amp;gt;CM3D2\Sybaris\GameData&amp;lt;/code&amp;gt;, create a new folder &amp;quot;FemaleUncensor&amp;quot; then pull all .tex uncensor files from converts into this folder.&amp;lt;br&amp;gt;&lt;br /&gt;
You can skip this step, If you don't need to male uncensor. but If you need to do the following:&amp;lt;br&amp;gt;&lt;br /&gt;
3. Download [http://ux.getuploader.com/cm3d2_d/download/24/cm3d2_d_24.zip ManTNP] or Sybaris Starter Pack&amp;lt;br&amp;gt;&lt;br /&gt;
Then put male uncensor into &amp;lt;code&amp;gt;CM3D2\Sybaris\GameData&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Second Step: Installation'''&amp;lt;br&amp;gt;&lt;br /&gt;
1. Download [http://pastebin.com/pTKGk0Ef YASDPlus Plugin] or Sybaris Starter Pack&amp;lt;br&amp;gt;&lt;br /&gt;
2. Copy file '''cm3d2.yasdplus.plugin.cs''' into folder &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\AutoCompile&amp;lt;/code&amp;gt;. when opening the game, the game will generate this files below&lt;br /&gt;
# cm3d2.yasdplus.plugin.dll in &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
# yasd.ini in &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config&amp;lt;/code&amp;gt;&lt;br /&gt;
When you get the above files, YASDPlus Plugin installation have been completed.&amp;lt;br&amp;gt;&lt;br /&gt;
''Note: You can setting uncensor in the game by opening '''yasd.ini''' file in Notepad. See the setting from [http://motimoti3d.jp/blog-entry-53.html here].''&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Technical_Help&amp;diff=22625</id>
		<title>Custom Maid 3D2/Technical Help</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Technical_Help&amp;diff=22625"/>
				<updated>2017-09-11T20:08:21Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: More info about YATranslator&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
=FAQ=&lt;br /&gt;
==Running the game==&lt;br /&gt;
*'''Q: I keep getting an &amp;quot;(0) Yotogi.Category enum parse error (character not japanese)&amp;quot; error when I run the game and I have tried both AppLocale and NTLEA?'''&lt;br /&gt;
: A: You can't use AppLocale to run the x64 version because AppLocale don't support x64 version. but you can use AppLocale to run the x86 version on Windows 7,8 by step below&lt;br /&gt;
# Copy files and folders CM3D2x86_Data and CM3D2x86.exe from installation folder into your game folder. (example: C:\KISS\CM3D2\)&lt;br /&gt;
# Right-click CM3D2x86.exe and select Run with Japanese locale. (you need [http://www.hongfire.com/forum/showthread.php/328830 HF pApploc] for the right-click options.)&amp;lt;br&amp;gt; '''''Note: HF pAppLoc doesn't work with Windows 10 or x64 version.'''''&lt;br /&gt;
: A: The best way for solve this problem is set '''window system locate to japanese''' but if you still want to run the x64 version or window 10 without set window system, you can try this [http://www.hongfire.com/forum/showthread.php/444096-KISS-Custom-Maid-3D-2-%28%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%A1%E3%82%A4%E3%83%893D2%29-Discussion-FAQ?p=3706481#post3706481 solution], which is using NTLEA x64.&lt;br /&gt;
&lt;br /&gt;
*'''Q: My game crashes doing in maid creation or doing change skin color and my graphic card is AMD. How to fix this problem?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Maybe this guide is helpful for you [http://www.hongfire.com/forum/showthread.php/445139-AMD-CRASH-FIX-FOR-Radeon-HD-Series AMD CRASH FIX FOR Radeon HD Series] or you can access [http://pastebin.com/t3m1Lg3h this] in case the website blocked.&lt;br /&gt;
&lt;br /&gt;
*'''Q: How do I install the translations?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: See [[Custom_Maid_3D_2/Technical_Help#Translate_Plus_Plugin|Translate Plus]] or [[Custom_Maid_3D_2/Technical_Help#YATranslator_Plugin|YATranslator]].&lt;br /&gt;
&lt;br /&gt;
*'''Q: I get this error when running the HF Patch: &amp;quot;... The game is an unsupported version. This patch requires version 1.03...&amp;quot;, what can I do?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Install the official 1.03 patch and then run the [[#The HF Patch|Custom Maid 3D 2 HF Patch]] again. There are mirrors to the official patch in the [http://www.hongfire.com/forum/showthread.php/444096 CM3D2 discussion].&lt;br /&gt;
&lt;br /&gt;
*'''Q: I get a &amp;quot;Daily panel&amp;quot; error during gameplay.'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Make sure that you have the official 1.03 patch installed (and it is correct version - x86 or x64) and then run the [[#The HF Patch|Custom Maid 3D 2 HF Patch]] again. There are mirrors to the official patch in the [http://www.hongfire.com/forum/showthread.php/444096 CM3D2 discussion].&lt;br /&gt;
&lt;br /&gt;
*'''Q: It keeps telling me that the &amp;quot;game main executable couldn't be found, path maybe invalid and it says that after I try to install the patch.&amp;lt;br&amp;gt;&lt;br /&gt;
: A:&lt;br /&gt;
&lt;br /&gt;
*'''Q: Incorrect Position UI, Transparent UI, White UI, Black screen stuck on Day 1, Night service skill name overlapping after update patch.'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Delete Folder &amp;quot;Assets&amp;quot; and &amp;quot;Texture&amp;quot; in &amp;lt;code&amp;gt;Sybaris\UnityInjector\Config&amp;lt;/code&amp;gt; and replace them with files download from [http://goo.gl/6CsKNi v1.49 UI translation]. This solve whatever problem you encouter (v1.49 UI translation for v1.52, older version you can find them in HF).&lt;br /&gt;
: '''''Note: this trouble often found after KISS update the game, be careful this solution in this specific to your game version.'''''&lt;br /&gt;
&lt;br /&gt;
==Gameplay==&lt;br /&gt;
*'''Q: I got this option for my maid to choose between Free and something. What does this mean? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You are choosing between making your [[Custom_Maid_3D_2/Gameplay/The_Maid_Profile#Maid_Type|Maid Type]]. There are two types of maid is personal (only has sex with you) and free (has sex with the customers). The first earns you less money than the second.&lt;br /&gt;
&lt;br /&gt;
*'''Q: How can I replay VIP scenes?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: &amp;lt;del&amp;gt;If you want to play them again, you must keep a save file before play the VIP. (After 100 days in game, VIP events that have been played over the first 99 days in game are again avalable to be played with forever but the same requirements are still applied as per the VIP event.)&amp;lt;/del&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
: A: After v1.21 and Plus Pack, you can replay unlocked VIP events in [[Custom_Maid_3D_2/Gameplay#Free_Mode|Free Mode]].&lt;br /&gt;
&lt;br /&gt;
*'''Q: What are red options during sex?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: These are '''one-time''' options for the skill. You can use them again next time if you use this skill again.&lt;br /&gt;
&lt;br /&gt;
*'''Q: How do I get more maids? I only have 1-2.'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You need to get your club '''out of debt''' first. Also, there is no upper limit on maids, but there is an upper limit on six working maids.&lt;br /&gt;
&lt;br /&gt;
*'''Q: How do I unlock new rooms? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Increase your [[Custom_Maid_3D_2/Gameplay#Club_Grade|Club Grade]] from cleaning, decorating and eval and other [[Custom_Maid_3D_2/Gameplay#Rooms|Rooms]] require expansion installation. This is possible while still in debt.&lt;br /&gt;
&lt;br /&gt;
*'''Q: After having sex with my maid, I got a notification. Something to do with being close? What does this mean? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: It means you've advanced your [[Custom_Maid_3D_2/Gameplay/The_Maid_Profile#Status|Relationship]] with your maid.&lt;br /&gt;
&lt;br /&gt;
*'''Q: How do I earn CR for pay off the 10m Debt?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You can earn a small amount 50k~100k CR of money by &amp;quot;Dispatch&amp;quot; maids during the daytime, but the most amount of money comes from &amp;quot;Entertain&amp;quot; on nighttime. Entertain can earn 200k~1m CR per night per maid depending on club grade. Both Free Maids and Personal Maids are able to entertain.&lt;br /&gt;
&lt;br /&gt;
*'''Q: It is said that I got &amp;quot;Ring&amp;quot; from the Lovers Trophy but I can't seem to find it... where can I find it?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: It's only unlocked by the time you got the &amp;quot;Lovers&amp;quot; Trophy. You still need to buy it from the shop for 10.000.000CR to equip the ring in the arms category.&lt;br /&gt;
&lt;br /&gt;
*'''Q: All of sudden, There is no &amp;quot;Talk to her&amp;quot; option... What am I doing wrong? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You didn't put either top or bottom clothes for her, which makes her feels too embarrassed to talk to you. Try to put some clothes instead you ecchi-goshujinsama.&lt;br /&gt;
&lt;br /&gt;
*'''Q: I can't seem to make the rental maid to do her VIP event? '''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: You need to supervise her daily activities to earn her trust until you trigger all the 3 specific events which occurs per-day, the last one will pop-up a dialogue that tells you the VIP event is unlocked. The VIP event only occurs once and is not replayable since she's a rental maid. Explained in [[Custom_Maid_3D_2/Gameplay/VIP_Events#NPC_Maid|NPC Maid VIP]]&lt;br /&gt;
&lt;br /&gt;
==Text Hooking - Visual Novel Reader==&lt;br /&gt;
*'''Q: Why can't I get VNR to work with the game?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: VNR doesn't work with the x64 version of the game, use the x86 version instead.&lt;br /&gt;
&lt;br /&gt;
*'''Q: I managed to sync VNR to CM3D2 v1.03 but I can't make it translate. The TL box won't come out. What's wrong?'''&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Either enable the VNR built in hooker or rollback; overwrite your current VNR folder.&lt;br /&gt;
&lt;br /&gt;
=Installed Guide=&lt;br /&gt;
More information can be found in [http://www.hongfire.com/forum/forum/hentai-lair/hentai-game-discussion/418479 CM3D2 Hongfire] or [https://www.reddit.com/r/cm3d2/comments/6faqro/support_megathread CM3D2 Reddit].&lt;br /&gt;
==Installing the Game==&lt;br /&gt;
[[File:CM3D2_Installer.png|thumb|Click the highlighted button to install]]&lt;br /&gt;
[[File:CM3D2_Insert_disk2.png|thumb|Insert disk 2]]&lt;br /&gt;
#Set the '''window system locate to japanese''' or download [http://www.hongfire.com/forum/showthread.php/328830 HF pApploc]&amp;lt;br&amp;gt; '''''Note: HF pAppLoc doesn't work with Windows 10 or x64 version.'''''&lt;br /&gt;
#Extract &amp;lt;code&amp;gt;cm3d2_1.iso&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;cm3d2_2.iso&amp;lt;/code&amp;gt; '''(DO NOT extract the .mds files)'''&lt;br /&gt;
#Mount &amp;lt;code&amp;gt;cm3d2_1.iso&amp;lt;/code&amp;gt; with [http://www.disk-tools.com/download/daemon Daemontools Lite] (If you have trouble using other mounting software, Daemontools Lite has been confirmed to work)&lt;br /&gt;
#'''DO NOT autorun''', but open the mounted dvd in explorer and click &amp;lt;code&amp;gt;Installer.exe&amp;lt;/code&amp;gt; if your computer locale already in japanese, otherwise, right-click &amp;lt;code&amp;gt;Installer.exe&amp;lt;/code&amp;gt; and select Run with Japanese locale as an administrator (you need [http://www.hongfire.com/forum/showthread.php/328830 HF pApploc] for the right-click options)&lt;br /&gt;
#Optional: Change the install folder (default is C:\KISS).&lt;br /&gt;
#Click the button &amp;lt;code&amp;gt;インストール&amp;lt;/code&amp;gt; to start the CM3D2 setup.&lt;br /&gt;
#Confirm that you want to install to that location and wait while the setup until setup asks for disk 2.&lt;br /&gt;
#Mount &amp;lt;code&amp;gt;cm3d2_2.iso&amp;lt;/code&amp;gt; and click Retry.&lt;br /&gt;
#Wait for the setup to finish and close the installer.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
==Updating Patch==&lt;br /&gt;
[[File:Kissupdatepage.JPG|thumb|right|KISS official update webpage]]&lt;br /&gt;
[[File:Kissupdate folder.JPG|thumb|right|Extracted .zip files]]&lt;br /&gt;
#Set the '''window system locate to japanese''' or download [http://www.hongfire.com/forum/showthread.php/328830 HF pApploc]&amp;lt;br&amp;gt; '''''Note: HF pAppLoc doesn't work with Windows 10 or x64 version.'''''&lt;br /&gt;
#Download the latest full update that is meant for the version you run (either x86 or x64).&amp;lt;br&amp;gt; For lastes update patch: http://kisskiss.tv/cm3d2/update.php&amp;lt;br&amp;gt; For old update patch: http://kisskiss.tv/cm3d2/oldupdate.php&amp;lt;br&amp;gt; Or visit forum  for mirrors update patch: [http://www.hongfire.com/forum/forum/hentai-lair/hentai-game-discussion/418479 CM3D2 discussion].&lt;br /&gt;
#Download the updater ver.1.00～1.12 (cm3d2_up_for_1_00-1_12)&lt;br /&gt;
#Extract the .zip file and execute the &amp;lt;code&amp;gt;update.exe&amp;lt;/code&amp;gt; located inside the extracted folder. (It will auto-detect your installation directory) you can simply execute the &amp;lt;code&amp;gt;update.exe&amp;lt;/code&amp;gt; if your computer locale already in japanese, otherwise, right-click &amp;lt;code&amp;gt;update.exe&amp;lt;/code&amp;gt; and select ''Run with Japanese locale as an administrator'' (you need [http://www.hongfire.com/forum/showthread.php/328830 HF pApploc] for the right-click options).&lt;br /&gt;
#Choose &amp;lt;code&amp;gt;適用&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;開始&amp;lt;/code&amp;gt;, and wait for the patch to be extracted and installed.&lt;br /&gt;
#Download the latest updater (example: cm3d2_up148_x86_sub or cm3d2_up148_x64_sub) and repeat ''step 4 and 5'' after downloading the latest updater.&lt;br /&gt;
#After update complete, next time you can update the latest patch into your game without update ver.1.00～1.12 again.&lt;br /&gt;
Additional screenshots for '''Step 5''' as below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[File:Kissupdate patch1.JPG|300px|center]] || [[File:Kissupdate patch2.JPG|300px|center]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''''1st Note:''' If the patch didn't detect your installation directory and/or somehow the update.exe bugged, you can overwrite the ''GameData'' folder, and you will also need to update the ''update.lst'' file, which is advanced for veteran users.''&lt;br /&gt;
&lt;br /&gt;
'''''2nd Note:''' The '''update.exe''' will not install an already installed patches/DLCs as seen in additional screenshots for Step 5 where the START option is '''''greyed out''''', it follows the ''update.lst'' file, in case you are wondering it is located on your CM3D2 Root directory. (example: ''C:\KISS\CM3D2\'')''&lt;br /&gt;
&lt;br /&gt;
==Installing Sybaris==&lt;br /&gt;
===Sybaris FAQ===&lt;br /&gt;
*'''Q: What is Sybaris?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Sybaris is loader that runs plugins other than the official plugins have been installed in the base game.&lt;br /&gt;
&lt;br /&gt;
*'''Q: What is the difference between Sybaris and Reipatcher?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Both loader have no difference in usability. The only difference is the methods of operation.&lt;br /&gt;
&lt;br /&gt;
*'''Q: Why use Sybaris?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Sybaris have the advantage better than Reipatcher is:&amp;lt;br&amp;gt;&lt;br /&gt;
# Does not affect the base game, you can go back to vanilla anytime.&amp;lt;br&amp;gt;&lt;br /&gt;
# Updating the game causes less problems.&lt;br /&gt;
&lt;br /&gt;
*'''Q: Sybaris have a disadvantage?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: Sybaris has the following disadvantages:&amp;lt;br&amp;gt;&lt;br /&gt;
# Many plugins for Sybaris are only available in japanese language.&amp;lt;br&amp;gt;&lt;br /&gt;
# Some Reipatcher plugins are incompatible with Sybaris, such as Unified Translation Loader.&lt;br /&gt;
&lt;br /&gt;
*'''Q: Sybaris need to install Reipatcher?&amp;lt;br&amp;gt;&lt;br /&gt;
: A: No&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
===Sybaris===&lt;br /&gt;
For an easy installation you can download: [https://mega.nz/#!XFJUQAjL!G2GMTKUt2XGCo94Q3SII5Ki02u1LtMEECyCa9QrEr-g Sybaris Starter Pack 1.52] or [http://www.hongfire.com/forum/forum/hentai-lair/hf-modding-translation/custom-maid-3d-2-mods/5816208-sybaris-aio-ultimate-english-expansion-1-52-2-1-beta-suggestions-are-welcome Sybaris AIO Ultimate English Expansion 1.52.2.4 Beta]&amp;lt;br&amp;gt;&lt;br /&gt;
This Package contains:&lt;br /&gt;
* Sybaris support v1.52+&lt;br /&gt;
* Plugins&lt;br /&gt;
* Translator&lt;br /&gt;
* Uncensor&lt;br /&gt;
&lt;br /&gt;
1. Download [https://ux.getuploader.com/cm3d2_e/download/317/cm3d2_e_317.zip Sybaris] or Sybaris Starter Pack&amp;lt;br&amp;gt;&lt;br /&gt;
2. Copy '''opengl32.dll''' and '''Sybaris''' folder into the game folder. example: &amp;lt;code&amp;gt;C:\KISS\CM3D2&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Please use opengl32.dll according to version game you play.&amp;lt;br&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;cm3d2_e_317\opengl32.dll&amp;lt;/code&amp;gt; for the 64bit version (x64).&lt;br /&gt;
# &amp;lt;code&amp;gt;cm3d2_e_317\x86\opengl32.dll&amp;lt;/code&amp;gt; for the 32bit version (x86).&lt;br /&gt;
&amp;lt;code&amp;gt;SybarisArcEditor&amp;lt;/code&amp;gt; is optional. This program will allow you to view and edit .arc files.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Basic Plugin===&lt;br /&gt;
1. Download [https://ux.getuploader.com/cm3d2_h/download/58/cm3d2_h_58.zip Basic Plugin] or Sybaris Starter Pack&amp;lt;br&amp;gt;&lt;br /&gt;
This Package contains:&lt;br /&gt;
* MaidVoicePitch Plugin&lt;br /&gt;
* ExternalSaveData Plugin&lt;br /&gt;
* FastFade Plugin&lt;br /&gt;
* AddModsSlider Plugin&lt;br /&gt;
* ExternalPreset Plugin&lt;br /&gt;
* ConsistentWindowPosition Plugin '''(Optional)'''&lt;br /&gt;
* EditSceneUndo Plugin '''(Optional)'''&lt;br /&gt;
* LogWindow Plugin '''(Optional)'''&lt;br /&gt;
* PersonalizedEditSceneSettings Plugin '''(Optional)'''&lt;br /&gt;
* SkillCommandShortCut Plugin '''(Optional)'''&lt;br /&gt;
* VoiceNormalizer Plugin '''(Optional)'''&lt;br /&gt;
2. Copy .dll files in folder &amp;lt;code&amp;gt;Loader&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Plugins\UnityInjector&amp;lt;/code&amp;gt; from basic plugin to sybaris in game folder.&lt;br /&gt;
# &amp;lt;code&amp;gt;cm3d2_h_58\ReiPatcherレス化プラグイン一式170606\Sybaris\Loader&amp;lt;/code&amp;gt; ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Loader&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;cm3d2_h_58\ReiPatcherレス化プラグイン一式170606\Sybaris\Plugins\Unityinjector&amp;lt;/code&amp;gt; ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
3. Copy files in folder &amp;lt;code&amp;gt;Plugins\UnityInjector\Config&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\UnityInjector\Config&amp;lt;/code&amp;gt; in game folder.&amp;lt;br&amp;gt;&lt;br /&gt;
4. For '''optional''' plugins, you can install them by copy .dll files in &amp;lt;code&amp;gt;Sybaris\Loader\オプション&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\オプション&amp;lt;/code&amp;gt; from basic plugin into Sybaris in game folder.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Note: '''FastFade Plugin''' will change the display of the game. If you don't need to use the plugin, then shouldn't be installed.''&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Translate Plus Plugin===&lt;br /&gt;
{{msgbox&lt;br /&gt;
|border=#ddd&lt;br /&gt;
|background=#ddd&lt;br /&gt;
|textcolor=#000&lt;br /&gt;
|message='''NOTE:''' TranslationPlus is known not to be directly compatible with CM3D2 1.49 or newer without editing the translation files. Consider using [[Custom_Maid_3D_2/Technical_Help#YATranslator_Plugin|YATranslator]] or proceed at your own risk.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
1. Download [https://github.com/zklm/CM3D2.TranslationPlus/releases Translate Plus Plugin] or Sybaris Starter Pack&amp;lt;br&amp;gt;&lt;br /&gt;
2. Copy files below in the translate plus folder to these folders.&lt;br /&gt;
# CM3D2.TranslationPlus.Sybaris.Patcher.dll ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Loader&amp;lt;/code&amp;gt;&lt;br /&gt;
# CM3D2.TranslationPlus.Hook ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
# CM3D2.TranslationPlus.Plugin ➡ &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
3. Translate Plus Plugin is require a translate data to run with the plugin. you can find translate data in [http://www.hongfire.com/forum/forum/hentai-lair/hf-modding-translation/custom-maid-3d-2-mods/5678372-cm3d2-system-text-translation HF] or [https://mega.nz/#!XFJUQAjL!G2GMTKUt2XGCo94Q3SII5Ki02u1LtMEECyCa9QrEr-g Sybaris Starter Pack], then put a translate file into &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config&amp;lt;/code&amp;gt; (for system text translate, go to step 2)&lt;br /&gt;
# Create a new folder &amp;quot;Assets&amp;quot; and put translate files into &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config\Assets&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Create a new folder &amp;quot;String&amp;quot; and put translate files into &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config\Strings&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Create a new folder &amp;quot;Texture&amp;quot; and put translate files into &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config\Texture&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===YATranslator Plugin===&lt;br /&gt;
YATranslator is a translation loader. It supports CM3D2 1.49 and newer, works with ReiPatcher and Sybaris, and replaces TranslationPlus and the Unified Translation Plugin.&lt;br /&gt;
&lt;br /&gt;
1. Download [https://github.com/denikson/CM3D2.YATranslator/releases YATranslator Plugin] or [http://www.hongfire.com/forum/forum/hentai-lair/hf-modding-translation/custom-maid-3d-2-mods/5816208-sybaris-aio-ultimate-english-expansion-1-52-2-1-beta-suggestions-are-welcome Sybaris AIO Ultimate English Expansion 1.52.2.4 Beta] &amp;lt;br&amp;gt;&lt;br /&gt;
2. '''Remove TranslationPlus or the Unified Translation Loader'''&amp;lt;br&amp;gt;&lt;br /&gt;
3. Follow the installation guides included in the READMEs&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====AutoTranslate====&lt;br /&gt;
Currently YATranslator a custom-fixed AutoTranslate Plugin to enable automatic Google translations.&lt;br /&gt;
You can find the latest version on [http://www.hongfire.com/forum/forum/hentai-lair/hf-modding-translation/custom-maid-3d-2-mods/5813782-plugin-yat-yet-another-translator-1-3-0-0-vpvr-subtitles-autotranslate?p=5814818#post5814818 HongFire].&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===YASDPlus Plugin===&lt;br /&gt;
'''First Step: Prepare File'''&amp;lt;br&amp;gt;&lt;br /&gt;
1. Download [https://mega.nz/#!G8Y3gIwL!6U5x1xWj-QzmP8CULD6OoaxuvbWJhR1SUlcKpx_aMtI Soft-Demosaic Plugin] (Password: byreisen)&amp;lt;br&amp;gt;&lt;br /&gt;
Copy file '''CM3D2.NoMosaic.Plugin.dll''' from the CM3D2.NoMosaic folder to &amp;lt;code&amp;gt;CM3D2\Sybaris\Plugins\UnityInjector&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
2. Next Step (If you have Sybaris Starter Pack, skip to step 2.3)&amp;lt;br&amp;gt;&lt;br /&gt;
Download [https://mega.nz/#!Y5hCXThS!jgbR9IFpBgFlT9V1-YEh9FpJK4ajoVweN9GOyTL5wrE Female Uncensor-Menelol(R4)] (Password: 4HF)&amp;lt;br&amp;gt;&lt;br /&gt;
Download [http://ux.getuploader.com/cm3d2_d/download/84/cm3d2_d_84.zip 適当ツールまとめ] &amp;lt;br&amp;gt;&lt;br /&gt;
# Go to folder &amp;lt;code&amp;gt;Girl Uncensor\UnityInjector\config&amp;lt;/code&amp;gt; of Female Uncensor-Menelol, find all .png file inside the folder.&amp;lt;br&amp;gt;&lt;br /&gt;
# Import .png files in Female Uncensor-Menelol folder to program '''[CM3D2]tex←→png変換.exe''' in &amp;lt;code&amp;gt;cm3d2_d_84\[CM3D2]適当ツールまとめ&amp;lt;/code&amp;gt; then convert .png to .tex, doing all the files until complete.&amp;lt;br&amp;gt;&lt;br /&gt;
# Go to folder &amp;lt;code&amp;gt;CM3D2\Sybaris\GameData&amp;lt;/code&amp;gt;, create a new folder &amp;quot;FemaleUncensor&amp;quot; then pull all .tex uncensor files from converts into this folder.&amp;lt;br&amp;gt;&lt;br /&gt;
You can skip this step, If you don't need to male uncensor. but If you need to do the following:&amp;lt;br&amp;gt;&lt;br /&gt;
3. Download [http://ux.getuploader.com/cm3d2_d/download/24/cm3d2_d_24.zip ManTNP] or Sybaris Starter Pack&amp;lt;br&amp;gt;&lt;br /&gt;
Then put male uncensor into &amp;lt;code&amp;gt;CM3D2\Sybaris\GameData&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Second Step: Installation'''&amp;lt;br&amp;gt;&lt;br /&gt;
1. Download [http://pastebin.com/pTKGk0Ef YASDPlus Plugin] or Sybaris Starter Pack&amp;lt;br&amp;gt;&lt;br /&gt;
2. Copy file '''cm3d2.yasdplus.plugin.cs''' into folder &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\AutoCompile&amp;lt;/code&amp;gt;. when opening the game, the game will generate this files below&lt;br /&gt;
# cm3d2.yasdplus.plugin.dll in &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
# yasd.ini in &amp;lt;code&amp;gt;Sybaris\Plugins\UnityInjector\Config&amp;lt;/code&amp;gt;&lt;br /&gt;
When you get the above files, YASDPlus Plugin installation have been completed.&amp;lt;br&amp;gt;&lt;br /&gt;
''Note: You can setting uncensor in the game by opening '''yasd.ini''' file in Notepad. See the setting from [http://motimoti3d.jp/blog-entry-53.html here].''&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/ReiPatcher&amp;diff=19433</id>
		<title>Custom Maid 3D2/Modding/ReiPatcher</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/ReiPatcher&amp;diff=19433"/>
				<updated>2016-01-03T11:06:02Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: Added links to an up-to-date guide&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{msgbox&lt;br /&gt;
|border=#ddd&lt;br /&gt;
|background=#ddd&lt;br /&gt;
|textcolor=#000&lt;br /&gt;
|message='''''This article is out of date and contains information that might be obsolete. You can find a newer guide for ReiPatcher [http://umaiumeunion.github.io/guides_reipatcher/01_preface.html here] and for UnityInjector [http://umaiumeunion.github.io/guides_unityinjector/01_preface.html here].'''''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
[http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] is an awesome tool made by Hongfire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei]. ReiPatcher allows you to apply all kinds of modifications to a game that is made with Unity: you can change how game behaves; you can translate the game into another language; you can edit sounds, textures, models and other in-game assets while the game is running. All in all, the possibilities are limitless!&lt;br /&gt;
&lt;br /&gt;
If somebody linked you to this page, it means you're one of hundreds of people who cannot really understand how to use this neat tool. On the other hand, if you stumbled upon the page yourself, you most likely are seeking for an easy-to-understand tutorial on how to set up and use ReiPatcher. Whichever it might be, '''you came to the right place'''. By reading this small tutorial you will become a professional ReiPatcher'er(er?) in no time!&lt;br /&gt;
&lt;br /&gt;
What are we waiting for? Let the patching begin!&lt;br /&gt;
&lt;br /&gt;
== Grabbing the tools and getting it organized ==&lt;br /&gt;
Before we can start patching, we need ReiPatcher downloaded!&lt;br /&gt;
&lt;br /&gt;
Head to [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and grab the tool! Of course, remember to thank Rei-sama for his hard work by giving him some reputation '''[http://www.hongfire.com/forum/reputation.php?do=addreputation&amp;amp;p=3703144 here]''' (which is one of the many reasons you should join the greate Hongfire community!).&lt;br /&gt;
&lt;br /&gt;
After you have the archive downloaded, extract it to some folder. If you are asked to enter a password, it is most likely &amp;lt;code&amp;gt;byreisen&amp;lt;/code&amp;gt; (if it's not, check the maid thread).&lt;br /&gt;
&lt;br /&gt;
After you have extracted everything, you'll find '''at least''' the following files:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Filename !! Purpose and some other information&lt;br /&gt;
|-&lt;br /&gt;
| ExIni.dll || Used by ReiPatcher and the majority of user-created plug-ins. Responsible for creating, editing and saving configuration files.&lt;br /&gt;
|-&lt;br /&gt;
| ExIni.pdb and ExIni.xml || Mainly used by developers to debug and have a documentation of the ExIni library. If you are not a developer, you don't really need these.&lt;br /&gt;
|-&lt;br /&gt;
| Mono.Cecil.dll and other DLLs starting with Mono.Cecil || The most important tool of ReiPatcher that is responsible for patching the game.&lt;br /&gt;
|-&lt;br /&gt;
| ReiPatcher.exe || The executable you are going to run every time you want (or need) to patch a game.&lt;br /&gt;
|-&lt;br /&gt;
| ReiPatcher.pdb and ReiPatcher.xml || Just as for ExIni.pdb and .xml, they are mainly intended for the developers. You don't really need them unless you are a developer. It is, however, advised that you to keep ReiPatcher.pdb, as it will make it easier to read possible errors.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now move these files to some directory of your preference. The main point is that all the files stay together. The best place is perhaps the same directory where your games are located. Simply create a folder called ReiPatcher there and put the extracted files in it.&lt;br /&gt;
&lt;br /&gt;
There you go! Now let us test whether ReiPatcher works! Simply hold &amp;lt;code&amp;gt;Shift&amp;lt;/code&amp;gt; and rihgt-click on the empty space in ReiPatcher folder. From the context menu that has just appeared select &amp;lt;code&amp;gt;Open command window here&amp;lt;/code&amp;gt;. A command prompt should now open. The cursor (_) should be next to the ReiPatcher's directory. Write &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; and hit &amp;lt;code&amp;gt;Enter&amp;lt;/code&amp;gt;. If you copied (or moved) everything correctly, you'll get (almost similar) prompt:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ReiPatcher 0.9.0.8&lt;br /&gt;
 .NET Assembly Patcher - Powered by Mono.Cecil&lt;br /&gt;
 Copyright © Usagirei 2015&lt;br /&gt;
 GIT master [aac43ce754149cbde635f4ef6d5b164aa796fba1]&lt;br /&gt;
 ==============================================================                                 &lt;br /&gt;
 Switch Usage:&lt;br /&gt;
 -fc &amp;lt;Config&amp;gt;            Force creation of new configuration file&lt;br /&gt;
 -c &amp;lt;Config&amp;gt;             Use or create of configuration file &lt;br /&gt;
 -w              Waits for user input after patching&lt;br /&gt;
 -r              Reloads latest Assembly backup &lt;br /&gt;
 &lt;br /&gt;
 Exit Codes:&lt;br /&gt;
  0                      Success&lt;br /&gt;
  1                      NoPatchesApplied&lt;br /&gt;
 -3                      InternalException&lt;br /&gt;
 -2                      FileNotFound&lt;br /&gt;
 -1                      DirectoryNotFound&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are all set! Now onto creating a game configuration!&lt;br /&gt;
&lt;br /&gt;
== Creating game configuration ==&lt;br /&gt;
Before patches can be applied, we need to create a configuration file that tells ReiPatcher where the game files are and where to find the patches to apply.&lt;br /&gt;
&lt;br /&gt;
If the game is officially supported by Hongfire community, you'll most likely find ready game configurations online. Most likely they are available on [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher's original thread].&lt;br /&gt;
&lt;br /&gt;
If, however you are in need to create a new configuration from scratch, simply open the console window in ReiPatcher's directory (by holding &amp;lt;code&amp;gt;Shift&amp;lt;/code&amp;gt;, right-clicking on the empty space in the folder and selecting &amp;lt;code&amp;gt;Open command window here&amp;lt;/code&amp;gt;) and type the following in the opened console window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ReiPatcher.exe -fc &amp;lt;NAME&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where &amp;lt;NAME&amp;gt; is the name of the configuration (you're pretty much free to choose what it shall be).&lt;br /&gt;
&lt;br /&gt;
Whichever way you choose to obtain the configuration file, it should be put in the same folder as ReiPatcher.exe. That is not necessary, of course, but it will be A LOT easier to reference the files when patching through the command window.&lt;br /&gt;
&lt;br /&gt;
Now that you have the configuration file, let us examine it. Grab your favourite text editor of your choice (which should obviously be Notepad++, right? RIGHT?!) and open the configuration file you downloaded or created. Within you should see a bunch of (probably weird) syntax. Here's a quick agenda for you to remind/teach how to read .INI files:&lt;br /&gt;
* Lines starting with &amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt; are called comments. They are ignored by ExIni (for the exception the ones starting with &amp;lt;code&amp;gt;@&amp;lt;/code&amp;gt;. They are called environment variables and mostly used to load and store path information (which may change depending on the computer and game).&lt;br /&gt;
* Lines of the form &amp;lt;code&amp;gt;Variable=Value&amp;lt;/code&amp;gt; are variables that are used by ReiPatcher or other patchers. In ReiPatcher they are primarily used to store paths to different folders.&lt;br /&gt;
* Lines of the form &amp;lt;code&amp;gt;[Name]&amp;lt;/code&amp;gt; are called groups. They -- obviously -- group multiple variables together. All variables between two group names (or between a group name and the end of the file) belong to one group. The name of the grouped variables is defined in the upper group name declaration.&lt;br /&gt;
&lt;br /&gt;
After this crash-course into ExIni, here are some of the most important variables used by ReiPatcher. You'll most likely want to edit those to your liking:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Variable name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PatchesDir&amp;lt;/code&amp;gt; || Path to the patcher DLLs for this game configuration. Can be either absolute (ie. starting with drive letter) or relative (only folder name(s)). Depending on the game you'll want this to be &amp;lt;code&amp;gt;&amp;lt;GAME NAME&amp;gt;_Patches&amp;lt;/code&amp;gt;. Therefore you'll need to put plug-ins' patch DLLs in the folder called &amp;lt;code&amp;gt;&amp;lt;GAME NAME&amp;gt;_Patches&amp;lt;/code&amp;gt; that you must create in ReiPatcher folder.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; || Path to game assemblies that are to be patched. If you downloaded the configuration from the Internet, you'll most likely want to leave this as is. In other cases it is most likely of the form &amp;lt;code&amp;gt;&amp;lt;GAME DIRECTORY&amp;gt;\&amp;lt;GAME NAME&amp;gt;_Data\Managed&amp;lt;/code&amp;gt; (which, of course, might change depending on the game.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Executable&amp;lt;/code&amp;gt; || Set this to the path to the game executable, if you want ReiPatcher to launch the game after patching is complete. Leave empty if you don't.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Arguments&amp;lt;/code&amp;gt; || Additional arguments to use when launching the game.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Directory&amp;lt;/code&amp;gt; || Root of the game (the one that contains the game's executable).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Any additional values might vary depending on the patches and tools you use, which is why we shall not go deeper into the topic.&lt;br /&gt;
&lt;br /&gt;
After you have added your game configuration (and created the folder for patches as specified in the game configuration file), you can test/run it with ReiPatcher. Simply open the console window in ReiPatcher directory and type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ReiPatcher.exe -c &amp;lt;NAME&amp;gt;.ini&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where &amp;lt;NAME&amp;gt; is the name of your configuration file. If everything went well (and your folder containing the patches is empty), you should see the following output:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ReiPatcher 0.9.0.8&lt;br /&gt;
 .NET Assembly Patcher - Powered by Mono.Cecil&lt;br /&gt;
 Copyright © Usagirei 2015&lt;br /&gt;
 GIT master [aac43ce754149cbde635f4ef6d5b164aa796fba1]&lt;br /&gt;
 ==============================================================================&lt;br /&gt;
 Loading configuration file: 'CM3D2x64.ini'&lt;br /&gt;
 ============================== Loading Patchers ==============================&lt;br /&gt;
 Loading Patchers&lt;br /&gt;
 No Patches Found&lt;br /&gt;
 ================================= Pre-Patch ==================================&lt;br /&gt;
 ============================= Loading Assemblies =============================&lt;br /&gt;
 ================================== Patching ==================================&lt;br /&gt;
 ================================= Post-Patch =================================&lt;br /&gt;
 ================================== Finished ==================================&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since we had no patches in the folder that we specified in the configuration file, no patches were applied! Let us now proceed to actually downloading installing the patches and actually applying them!&lt;br /&gt;
&lt;br /&gt;
== Installing the patches ==&lt;br /&gt;
We're almost there! The only step left is to apply the patches!&lt;br /&gt;
&lt;br /&gt;
Download the plug-ins of your choice and extract the downloaded archives.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there are no strict rules on how to name either the folders in the archive or how to call the DLLs themselves. Therefore, '''always consult the README included with the plug-ins first!''' That being said, the most common way to divide the DLLs and other files in the plug-in is to divide them into three folders: &amp;lt;code&amp;gt;Manged&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ReiPatcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;UnityInjector&amp;lt;/code&amp;gt;. If that's the case, all you need to do is:&lt;br /&gt;
* Copy the contents of &amp;lt;code&amp;gt;Manged&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;Game directory&amp;gt;\&amp;lt;GAME&amp;gt;_Data\Managed&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;&amp;lt;Game directory&amp;gt;&amp;lt;/code&amp;gt; is the path to the game root (the directory where the game's extecutable is) and &amp;lt;code&amp;gt;&amp;lt;GAME&amp;gt;&amp;lt;/code&amp;gt; is the game code with the possible addition of some other codes, like CPU architecture.&lt;br /&gt;
* Copy the contents of &amp;lt;code&amp;gt;ReiPatcher&amp;lt;/code&amp;gt; to the patches folder specified in the game's configuration file.&lt;br /&gt;
* Copy the contents of &amp;lt;code&amp;gt;UnityInjector&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;Game directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt; if the folder does not exist yet, create it.&lt;br /&gt;
&lt;br /&gt;
Other times the developer doesn't bother to separate the DLLs into differenet folders. In these cases they most likely specify the purpose of the DLL by their name. Again, there are not strict rules on this either, but it seems that most developers name their plug-ins in the following manner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;GAME&amp;gt;.&amp;lt;Plugin name&amp;gt;.&amp;lt;Type&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In that case &amp;lt;code&amp;gt;&amp;lt;GAME&amp;gt;&amp;lt;/code&amp;gt; is the game code, &amp;lt;code&amp;gt;&amp;lt;Plugin name&amp;gt;&amp;lt;/code&amp;gt; is the name of the plug-in and &amp;lt;code&amp;gt;&amp;lt;Type&amp;gt;&amp;lt;/code&amp;gt; is the type of the DLL. Here are the most common type names and where to place the DLLs with that type:&lt;br /&gt;
* &amp;lt;code&amp;gt;Hook&amp;lt;/code&amp;gt; (also sometimes blank or &amp;lt;code&amp;gt;Core&amp;lt;/code&amp;gt;): put to &amp;lt;code&amp;gt;&amp;lt;Game directory&amp;gt;\&amp;lt;GAME&amp;gt;_Data\Managed&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;&amp;lt;Game directory&amp;gt;&amp;lt;/code&amp;gt; is the path to the game root (the directory where the game's extecutable is) and &amp;lt;code&amp;gt;&amp;lt;GAME&amp;gt;&amp;lt;/code&amp;gt; is the game code with the possible addition of some other codes, like CPU architecture.&lt;br /&gt;
* &amp;lt;code&amp;gt;Patch&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Patcher&amp;lt;/code&amp;gt;): Put to the patches folder specified in the game's configuration file.&lt;br /&gt;
* &amp;lt;code&amp;gt;Plugin&amp;lt;/code&amp;gt;: Put to &amp;lt;code&amp;gt;&amp;lt;Game directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt; if the folder does not exist yet, create it.&lt;br /&gt;
&lt;br /&gt;
=== The moment of truth ===&lt;br /&gt;
&lt;br /&gt;
When you have put everything into place, it is time to run ReiPatcher. Open command window in ReiPatcher folder and type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ReiPatcher.exe -c &amp;lt;NAME&amp;gt;.ini&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where &amp;lt;NAME&amp;gt; is the name of your configuration file. If everything went well, you'll see the green text that specifies that every patch has been applied successfully. Horaay! Now you can enjoy your game with the new plug-ins!&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
We briefly discussed how to install ReiPatcher, how to create own game configurations and how to install and apply patches. Much information has been omitted for the sake of simplicity, but this tutorial serves as a nice crash-course into the world of Unity Engine patching.&lt;br /&gt;
&lt;br /&gt;
I hope that you, dear reader, have grasped the most essential knowledge of being a ReiPatcher'er(er?)(er??). Whenever you have issues with patching the game, always consult this tutorial or the original ReiPatcher thread (unless you will get linked back to this tutorial, that is -- in which case you have missed something very obvious).&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=19432</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=19432"/>
				<updated>2016-01-03T11:05:03Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: Added links to an up-to-date guide&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{msgbox&lt;br /&gt;
|border=#ddd&lt;br /&gt;
|background=#ddd&lt;br /&gt;
|textcolor=#000&lt;br /&gt;
|message='''''This article is out of date and contains information that might be obsolete. You can find a newer guide for ReiPatcher [http://umaiumeunion.github.io/guides_reipatcher/01_preface.html here] and for UnityInjector [http://umaiumeunion.github.io/guides_unityinjector/01_preface.html here].'''''.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;includeonly&amp;gt;[[Category:Stubs]]&amp;lt;/includeonly&amp;gt;&lt;br /&gt;
&amp;lt;noinclude&amp;gt;[[Category:Article_management_templates]]&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Please note that owing to ever-so-evolving patching tools some parts of the tutorial may be outdated. The developers of said tools try their best to bring more features while trying to preserve the original programming routines. However, changes happen and the editors of this wiki attempt to update the documentation as fast as possible.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be almost impossible to manipulate, which is due to the code being mostly unmanaged (notice that the managed code is still compiled into CIL, albeit with &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt; tag.).&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
'''NOTE:''' Since ReiPatcherPlus 2.0, the library has undergone some major changes in structure. Therefore, note that some of parts of this page concerning ReiPatcherPlus might be outdated.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2(x84/x64)_Data\Managed&amp;lt;/code&amp;gt; folder at the very least.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Inspecting original code with a decompiler ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&amp;lt;/br&amp;gt;&lt;br /&gt;
'''Note:''' You can copy &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; as well, but remember that if you intend on using UnityInjector along with ReiPatcher, consider referencing the assembly directly from game directory instead. That way, after ReiPatcher had applied the patches, the IDE will automatically pick up updated method and visibility definitions.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming conventions ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, as of this moment, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. The hook DLL acts more often than not as a bridge between the game's own internal API and our plug-in code.&lt;br /&gt;
&lt;br /&gt;
If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good practice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies. &lt;br /&gt;
The patcher DLL is used by ReiPatcher to allow the plug-in developer to inject custom calls to the hook methods, change member field access and adding own code.&lt;br /&gt;
&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
Every assembly that one wishes to be patched must be requested. Otherwise it might not be included into the patching cycle.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times and on the right assemblies.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if our patch has already been applied to the specified assembly. That way we can avoid injecting the same code twice.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
The contents of the method depend on the situation. However, in almost all cases patching requires using various methods provided by Mono.Cecil to alter the contents of classes and methods.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps if we are to use pure Cecil and CIL:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, method search and injecting can be done easier with ReiPatcherPlus.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here are the main steps in using ReiPatcherPlus:&lt;br /&gt;
&lt;br /&gt;
'''1. Acquiring the type definitions'''&amp;lt;br/&amp;gt;&lt;br /&gt;
This is done simply with Mono.Cecil's &amp;lt;code&amp;gt;ModuleDefinition.GetType(string name)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
 TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''2. Getting the target method and the appropriate hook'''&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides an extension to Mono.Cecil: &amp;lt;code&amp;gt;TypeDefinition.GetMethod(string name)&amp;lt;/code&amp;gt; which searches for the first method with the given name.&amp;lt;br/&amp;gt;&lt;br /&gt;
Furthermore, to get a suiting hook method, we can use &amp;lt;code&amp;gt;GetHookMethod(MethodDefinition target, TypeDefinition hookType, string hookName, MethodFeatures features)&amp;lt;/code&amp;gt; which finds a suitable hook method that matches both the target method and the given criteria.&lt;br /&gt;
Since our hook method has only a parameter of the target type, only using the feature &amp;lt;code&amp;gt;MethodFeatures.PassTargetType&amp;lt;/code&amp;gt; will suffice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
 MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more detailed discussion on method features and &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, refer to the later sections.&lt;br /&gt;
&lt;br /&gt;
'''3. Injecting the code'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Having created an instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt;, we can now simply use ReiPatcherPlus's &amp;lt;code&amp;gt;AttachMethod(MethodHook hook, int codeOffset)&amp;lt;/code&amp;gt;. Since the hook method was searched with &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, one can be sure that the hook method is in fact injectable into the target method.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;int codeOffset&amp;lt;/code&amp;gt; specifies the index of the IL code to start the injection from. Since we want to add the hook at the beginning of the &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;, we simply pass 0:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 this.AttachMethod(hookMethod, 0);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putting it all together we get a fancy patch method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Get type definitions for the UIButton and the hook class&lt;br /&gt;
     TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
     TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
     // Get the method definition for OnClick and OnClickHook&lt;br /&gt;
     // GetHookMethod assures that the created MethodHook instance contains a valid hook for OnClick&lt;br /&gt;
     MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
     MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
     &lt;br /&gt;
     // Passing 0 will inject the hook method at the beginning of OnClick method&lt;br /&gt;
     this.AttachMethod(hookMethod, 0);&lt;br /&gt;
     &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Box1 start}}&lt;br /&gt;
'''NOTE:''' The alternative below is listed only for legacy reasons. ReiPatcherPlus 2.0+ marks &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; as obsolete. Consider using the above-mentioned code.&lt;br /&gt;
{{Boxes end}}&lt;br /&gt;
&lt;br /&gt;
Alternatively, ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
             TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
             &lt;br /&gt;
             MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
             MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
             &lt;br /&gt;
             this.AttachMethod(hookMethod, 0);&lt;br /&gt;
             &lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL (using UnityInjector) ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehaviour&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that the name of plug-in's INI configuration file will be the same as plug-in class name. In our case, calling &amp;lt;code&amp;gt;SaveConfig()&amp;lt;/code&amp;gt; will create a configuration file named &amp;lt;code&amp;gt;HelloWorldPlugin.ini&amp;lt;/code&amp;gt; which will be saved to &amp;lt;code&amp;gt;&amp;lt;Game's main directory&amp;gt;\UnityInjector\Config&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command below&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Source code and example projects ==&lt;br /&gt;
Below is a list of different projects written for ReiPatcher and UnityInjector. The projects can be used as templates for own projects.&lt;br /&gt;
* [https://github.com/usagirei/CM3D2_CameraControlEx Extended Camera Control] by [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei]&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
In the examples we shall use the following class that contains potential methods to hook:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         protected enum SwallowType&lt;br /&gt;
         {&lt;br /&gt;
             European,&lt;br /&gt;
             African&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
         private float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public float GetNeededSwallows(float distance);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         public static T FirstSwallow&amp;lt;T&amp;gt;(List&amp;lt;T&amp;gt; swallows);&lt;br /&gt;
         public static T FirstSwallow&amp;lt;T&amp;gt;(List&amp;lt;T&amp;gt; swallows, T addition);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting methods and fields ===&lt;br /&gt;
ReiPatcherPlus adds two new extension methods to Mono.Cecil that allow to locate method definitions in their respected types.&lt;br /&gt;
Those methods are added as extensions to &amp;lt;code&amp;gt;Mono.Cecil.TypeDefinition&amp;lt;/code&amp;gt; type.&amp;lt;br/&amp;gt;&lt;br /&gt;
Those two methods are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodDefinition GetMethod(string methodName);&lt;br /&gt;
 MethodDefinition GetMethod(string methodName, params TypeReference[] paramTypes);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;methodName&amp;lt;/code&amp;gt; || Name of the method to search for.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;paramTypes&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;TypeReference&amp;lt;/code&amp;gt; representation of method parameters. Used to search for the exact overload of a method.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Furthermore, one can easily acquire member fields (delegates, variables) of the type. That is done with the method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 FieldDefinition GetField(string memberName);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where &amp;lt;code&amp;gt;memberName&amp;lt;/code&amp;gt; is name of the member to search for.&lt;br /&gt;
&lt;br /&gt;
In both cases, the methods will return &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;, if the fitting method/field has not been found. Therefore, it is up to the developer to make sure the provided parameters point to a valid method or field. &lt;br /&gt;
In some cases, the programmer may need to perform null checking.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Will return GetNeededSwallows(int)&lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Will return GetNeededSwallows(float)&lt;br /&gt;
 MethodDefinition m2 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;, Parameter.FromType&amp;lt;float&amp;gt;());&lt;br /&gt;
 &lt;br /&gt;
 FieldDefinition f1 = swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Handling parameters ===&lt;br /&gt;
To make turning &amp;lt;code&amp;gt;System.Type&amp;lt;/code&amp;gt; and normal type declarations into dummy &amp;lt;code&amp;gt;TypeReference&amp;lt;/code&amp;gt;s to use with ReiPatcherPlus, &amp;lt;code&amp;gt;Parameter&amp;lt;/code&amp;gt; class was created.&lt;br /&gt;
The class houses a panoply of useful methods to create &amp;quot;dummy type references&amp;quot; (they are not actual references to the real types -- instead, they are containers for type information used method search methods).&amp;lt;br/&amp;gt;&lt;br /&gt;
Such methods are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeReference FromType(Type type, params string[] genericTypeNames);&lt;br /&gt;
 TypeReference FromType&amp;lt;T&amp;gt;();&lt;br /&gt;
 TypeReference FromTypeRef(Type type, params string[] genericTypeNames);&lt;br /&gt;
 &lt;br /&gt;
 TypeReference CreateGeneric(string name);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the first four methods, the parameter descriptions are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;System.Type&amp;lt;/code&amp;gt; representation of the given type. Can be acquired with &amp;lt;code&amp;gt;typeof(TypeName)&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;genericTypeNames&amp;lt;/code&amp;gt; || Names of the generic types. Used only, if the provided &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; has undefined generic parameters.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; || Type name of the type to be converted. Calling &amp;lt;code&amp;gt;FromType&amp;lt;T&amp;gt;()&amp;lt;/code&amp;gt; has the same effect as &amp;lt;code&amp;gt;FromType(typeof(T))&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
As for &amp;lt;code&amp;gt;CreateGeneric&amp;lt;/code&amp;gt;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; || Name of the generic type to create.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note that in order for &amp;lt;code&amp;gt;GetMethod&amp;lt;/code&amp;gt; to succeed with generic types, the names of those must stay the same. If the original method had a generic type &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;, one must make the type with &amp;lt;code&amp;gt;Parameter.MakeGeneric(&amp;quot;T&amp;quot;)&amp;lt;/code&amp;gt; in order for the method to be found.&lt;br /&gt;
The same principle must hold when matching target method parameters with the hook method parameters.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // t1 and t2 are technically the same &lt;br /&gt;
 TypeReference t1 = Parameter.FromType(typeof(int));&lt;br /&gt;
 TypeReference t2 = Parameter.FromType&amp;lt;int&amp;gt;();&lt;br /&gt;
 &lt;br /&gt;
 // Creates a type of List&amp;lt;T&amp;gt;&lt;br /&gt;
 TypeReference t3 = Parameter.FromType(typeof(List&amp;lt;&amp;gt;), &amp;quot;T&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Creates a reference type System.Boolean&amp;amp;&lt;br /&gt;
 TypeReference t4 = Parameter.FromTypeRef(typeof(bool));&lt;br /&gt;
 &lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m3 = swallowType.GetMethod(&amp;quot;MakeFly&amp;quot;, Parameter.FromType&amp;lt;bool&amp;gt;(), Parameter.FromType&amp;lt;float&amp;gt;());&lt;br /&gt;
 MethodDefinition m4 = swallowType.GetMethod(&amp;quot;FirstSwallow&amp;quot;, Parameter.FromType(typeof(List&amp;lt;&amp;gt;), &amp;quot;T&amp;quot;), Parameter.CreateGeneric(&amp;quot;T&amp;quot;));&lt;br /&gt;
 &lt;br /&gt;
 // WILL NOT WORK: The provided generic types differ from the original definition&lt;br /&gt;
 MethodDefinition m5 = swallowType.GetMethod(&amp;quot;FirstSwallow&amp;quot;, Parameter.FromType(typeof(List&amp;lt;&amp;gt;),&amp;quot;A&amp;quot;), Parameter.CreateGeneric(&amp;quot;G&amp;quot;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The MethodHook type and getting hooks ===&lt;br /&gt;
To provide an easy patching experience, ReiPatcherPlus includes &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; container that exposes the following get-only properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Hook&amp;lt;/code&amp;gt; || Method definition of the hook method. Will be hooked to the target.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Features&amp;lt;/code&amp;gt; || Additional criteria by which the hook method was chosen. Refer to the next subsection for more information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Target&amp;lt;/code&amp;gt; || Method definition of the method to hook (target method).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The creation of the &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; instance is controlled internally from ReiPatcherPlus. That way the library guarantees that the specified hook-target pair is valid and injectable.&lt;br /&gt;
&lt;br /&gt;
Currently there are two ways of getting the instance: by using &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; extension &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt; or by calling &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The exact definitions are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodHook GetHookMethod(MethodDefinition target, &lt;br /&gt;
                          TypeDefinition hookType, &lt;br /&gt;
                          string hookName, &lt;br /&gt;
                          MethodFeatures features, &lt;br /&gt;
                          params FieldDefinition[] memberReferences);&lt;br /&gt;
 &lt;br /&gt;
 MethodHook MethodHook.FromMethodDefinition(MethodDefinition target, &lt;br /&gt;
                                            MethodDefinition hook, &lt;br /&gt;
                                            MethodFeatures features, &lt;br /&gt;
                                            params FieldDefinition[] memberReferences);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The parameter description is the following:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;target&amp;lt;/code&amp;gt; || The method definition of the method which is to be hooked.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || The type (class/struct) that possesses the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; || The criteria by which the hook method should be chosen. Defines the structure of the hook method. Refer to the next subsection for more information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memberReferences&amp;lt;/code&amp;gt; || If one of the criteria is &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt;, specifies the fields that are to be passed to the method.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;hook&amp;lt;/code&amp;gt; || Method definition of the hook method.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
While using the methods, note the following:&lt;br /&gt;
* When using &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, the final &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; might be different from the ones specified. That is simply because the method adapts to its passed parameters to find the best hook method.&lt;br /&gt;
However, the method attempts to find the best hook without throwing any exceptions (for the exception of &amp;lt;code&amp;gt;ArgumentException&amp;lt;/code&amp;gt; if the provided member fields do not belong to the target type).&lt;br /&gt;
* &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt; strictly checks whether the provided target and hook are injectable. If a discrepancy is found, the method will throw an exception containing the reason the method failed.&lt;br /&gt;
* Prefer using &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, as it mostly exception-free and will return either a working instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Method Features ====&lt;br /&gt;
To allow the developer to freely choose which kind of hook to use, what parameters to pass and what to return, ReiPatcherPlus allows to specify certain criteria that define the layot of the hook method.&lt;br /&gt;
Albeit allowing different set of parameters to be passed, the hook method must have its parameters in a certain order for ReiPatcherPlus to work with them.&lt;br /&gt;
&lt;br /&gt;
Below is the hook method template with numbered positions and a table of what types are allowed in place of those positions and which &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; fields to use to enable those positions:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static &amp;lt;2.1&amp;gt; MyHookMethod(&amp;lt;1&amp;gt;, &amp;lt;2.2&amp;gt;, &amp;lt;3&amp;gt;, &amp;lt;4&amp;gt;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; field !! Position value replacement, if feature specified (only types and prefixes specified) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.None&amp;lt;/code&amp;gt; || &amp;lt;1&amp;gt;, &amp;lt;2.2&amp;gt;, &amp;lt;3&amp;gt;, &amp;lt;4&amp;gt; = Empty&amp;lt;br/&amp;gt;&amp;lt;2.1&amp;gt; = &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || The method may not have any of the features.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassTargetType&amp;lt;/code&amp;gt; || &amp;lt;1&amp;gt; = Target type || The method may be passed a reference to the target type that initially called the hooked method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; || &amp;lt;2.1&amp;gt; = &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;If target has a return type:&amp;lt;br/&amp;gt;&amp;lt;2.2&amp;gt; = &amp;lt;code&amp;gt;out &amp;lt;return type&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;Otherwise:&amp;lt;br/&amp;gt;&amp;lt;2.2&amp;gt; = Empty || The hook method is a redirect and thus may be passed a reference to the return value (if there is such). If the the target method has a return value of type &amp;lt;code&amp;gt;&amp;lt;return type&amp;gt;&amp;lt;/code&amp;gt;, a parameter of the same type is passed as a reference to the hook method.&amp;lt;br/&amp;gt;'''Note:''' If the feature is not specified, &amp;lt;2.1&amp;gt; must be &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt; || &amp;lt;3&amp;gt; = &amp;lt;code&amp;gt;ref &amp;lt;type1&amp;gt;, ref &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass references to the target type's member fields (assuming target method is not static) specified by the &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; creation method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMethodParametersByValue&amp;lt;/code&amp;gt; || &amp;lt;4&amp;gt; = &amp;lt;code&amp;gt;&amp;lt;type1&amp;gt;, &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass its own parameters to the hook. Since they are passed by value, they cannot be altered.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMethodParametersByReference&amp;lt;/code&amp;gt; || &amp;lt;4&amp;gt; = &amp;lt;code&amp;gt;ref &amp;lt;type1&amp;gt;, ref &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass its own parameters to the hook. Since they are passed by reference, they can be altered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Some important things to point out:&lt;br /&gt;
* The hook method '''must''' be public and static! Otherwise it is impossible to hook it anywhere.&lt;br /&gt;
* Some of the above-mentioned features can be left out. However the order of the parameters must be always preserved!&lt;br /&gt;
* If &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; is set, the hook method must return a &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the hook method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the execution of the original target method's instructions is interrupted; the target method simply returns the result value it got from the hook method (if any). In the contrary, if the hook method return &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the original target method will continue its execution after the hook method has completed executing its instructions.&lt;br /&gt;
* Legacy notice: &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; makes ReiPatcherPlus search for a redirect method. However, since both hooking and redirecting have been combined into one single method, there is no point in differentiating between them anymore.&lt;br /&gt;
&lt;br /&gt;
The features may be combined with a logical OR operator (&amp;lt;code&amp;gt;|&amp;lt;/code&amp;gt;). In addition to the features above, the &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; enumeration has the following feature combinations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Feature !! Combination equivalent&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.All_ByValue&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;MethodFeatures.PassTargetType | MethodFeatures.PassReturn | MethodFeatures.PassMemberReferences | MethodFeatures.PassMethodParametersByValue&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.All_ByReference&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;MethodFeatures.PassTargetType | MethodFeatures.PassReturn | MethodFeatures.PassMemberReferences | MethodFeatures.PassMethodParametersByReference&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 // Getting type definition for the class that contains all the hook methods&lt;br /&gt;
 TypeDefinition hookType = HookModule.GetType(&amp;quot;MyHookNamespace.Hook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 MethodDefinition m2 = swallowType.GetMethod(&amp;quot;MakeFly&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
 // Valid hook method prototype: public static void GetNeededSwallowsHook1()&lt;br /&gt;
 MethodHook hookM1 = this.GetHookMethod(m1, &lt;br /&gt;
                                        hookType, &lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook1&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.None);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool GetNeededSwallowsHook2(Swallow self, out float result, int coconuts)&lt;br /&gt;
 MethodHook hookM2 = this.GetHookMethod(m1,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook2&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByValue);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool GetNeededSwallowsHook3(Swallow self, out float result, ref int coconuts)									&lt;br /&gt;
 MethodHook hookM3 = this.GetHookMethod(m1,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook3&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByReference);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool MakeFlyHook(Swallow self, out float result, ref float airSpeedVelocity, int coconuts)									&lt;br /&gt;
 MethodHook hookM4 = this.GetHookMethod(m2,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;MakeFlyHook&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMemberReferences&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByValue,&lt;br /&gt;
                                        swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;));&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition hookMethod = hookType.GetMethod(&amp;quot;MakeFlyHook2&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool MakeFlyHook(Swallow self, out float result, ref float airSpeedVelocity, ref int coconuts)									&lt;br /&gt;
 MethodHook hookM5 = MethodHook.FromMethodDefinition(m2,&lt;br /&gt;
                                                     hookMethod,&lt;br /&gt;
                                                     MethodFeatures.All_ByReference,&lt;br /&gt;
                                                     swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Injecting the methods ===&lt;br /&gt;
Finally, ReiPatcherPlus provides a functionality to patch methods. That can be done with &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
The exact definitions and parameter descriptions are below:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void AttachMethod(MethodHook hook, int codeOffset);&lt;br /&gt;
 void AttachMethod(MethodDefinition target, &lt;br /&gt;
                   MethodDefinition hook, &lt;br /&gt;
                   int codeOffset, &lt;br /&gt;
                   MethodFeatures features,&lt;br /&gt;
                   params FieldDefinition[] memberReferences);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;target&amp;lt;/code&amp;gt; || The method definition of the method which is to be hooked.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodDefinition hook&amp;lt;/code&amp;gt; || Method definition of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; || The criteria by which the hook method should be chosen. Defines the structure of the hook method. '''Default: ''' &amp;lt;code&amp;gt;MethodFeatures.None&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memberReferences&amp;lt;/code&amp;gt; || If one of the criteria is &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt;, specifies the fields that are to be passed to the method.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;MethodHook hook&amp;lt;/code&amp;gt; || An instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; that contains all the appropriate information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;codeOffset&amp;lt;/code&amp;gt; || An index value of an IL instruction in the target method from which to begin injection. If set to negative, will begin counting from the last instruction of the target method, where -1 is being the last instruction.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Elementary, these two methods will automatically inject the needed CIL instructions depending on the chosen hook/target method.&amp;lt;br/&amp;gt;&lt;br /&gt;
The latter method will verify the compatibility between the target and the hook before applying the patch. That method is equivalent to calling &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt; and then &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Most of the time setting code offset to 0 will be sufficient for plug-ins. However, if one wants to place the hook at a certain place, refer to the previous sections on how to decompile the .NET code. Most of the decompilers come with IL decompilers bundled (like ILSpy), which allows to inspect pure IL instructions to find the perfect attachment point.&lt;br /&gt;
&lt;br /&gt;
Note as well that &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt; will always add its own CIL instructions '''before''' the specified code offset! That is done to prevent the developers from inserting method hooks after the &amp;lt;code&amp;gt;ret&amp;lt;/code&amp;gt; instruction that is always present as a last IL instruction in every method. Any code insterted after the said instruction is simply neglected by the machine.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 TypeDefinition hookType = HookModule.GetType(&amp;quot;MyHookNamespace.Hook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method prototype: public static void GetNeededSwallowsHook1()&lt;br /&gt;
 MethodHook hookM1 = this.GetHookMethod(m1, &lt;br /&gt;
                                        hookType, &lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook1&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.None);&lt;br /&gt;
 &lt;br /&gt;
 this.AttachMethod(hookM1, 0);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Debugging functions ===&lt;br /&gt;
ReiPatcherPlus provides simple methods for patcher message logging. All of the logging methods are located in &amp;lt;code&amp;gt;RPPLogger&amp;lt;/code&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
However, to enable logging, one must use the DEV version of the ReiPatcherPlus (slightly larger file size than normal ReiPatcherPlus).&lt;br /&gt;
After that, one can set &amp;lt;code&amp;gt;RPPLogger.VERBOSE_LEVEL&amp;lt;/code&amp;gt; variable to enable logging of certain methods.&lt;br /&gt;
&lt;br /&gt;
Possible variable values are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.None&amp;lt;/code&amp;gt; || Don't output any messages&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.Patcher&amp;lt;/code&amp;gt; || Output patcher-related messages (getting hook methods, attaching methods, etc.).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.Cecil&amp;lt;/code&amp;gt; || Output Mono.Cecil-related extension method messages. Includes parameter equality checking and method searching.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The flags can be combined with a logical OR (&amp;lt;code&amp;gt;|&amp;lt;/code&amp;gt;) operator.&lt;br /&gt;
&lt;br /&gt;
If one whishes to output own logging messages, it is possible through the following methods located in &amp;lt;code&amp;gt;RPPLogger&amp;gt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void Log(string message, VerboseLevel level, bool addPrefix);&lt;br /&gt;
 void LogLine(string message, VerboseLevel level, bool addPrefix);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the parameters:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt; || Message to output.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; || The level to output the message to. Used to filter the output based on selected levels.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;addPrefix&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will append a prefix specified on &amp;lt;code&amp;gt;RPPLogger.PREFIX&amp;lt;/code&amp;gt; before the specified &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The difference between the methods is that the latter will add a line break to the message, while the former one will not.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Set verbose level to patcher only&lt;br /&gt;
 RPPLogger.VERBOSE_LEVEL = RPPLogger.VerboseLevel.Patcher;&lt;br /&gt;
 &lt;br /&gt;
 // Will be shown in ReiPatcher console&lt;br /&gt;
 RPPLogger.LogLine(&amp;quot;Hello, log!&amp;quot;, RPPLogger.VerboseLevel.Patcher);&lt;br /&gt;
 &lt;br /&gt;
 // Won't be seen in ReiPatcher&lt;br /&gt;
 RPPLogger.LogLine(&amp;quot;I am hidden!&amp;quot;, RPPLogger.VerboseLevel.Cecil);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Legacy and other obsolete methods ===&lt;br /&gt;
These methods are marked as obsolete and must not be used. Instead, use the newer functionality of ReiPatcherPlus.&lt;br /&gt;
&lt;br /&gt;
==== Method hooking ====&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Method redirecting ====&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Template:Nav/Custom_Maid_3D2&amp;diff=18878</id>
		<title>Template:Nav/Custom Maid 3D2</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Template:Nav/Custom_Maid_3D2&amp;diff=18878"/>
				<updated>2015-09-27T00:00:54Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: Added a link to ReiPatch guide&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* '''[[Custom Maid 3D 2/Technical Help|FAQ &amp;amp; Technical Help]]'''&lt;br /&gt;
&lt;br /&gt;
* '''[[Custom Maid 3D 2/Gameplay|Gameplay]]'''&lt;br /&gt;
** [[Custom Maid 3D 2/Gameplay/The Maid Profile|The Maid Profile]]&lt;br /&gt;
** [[Custom Maid 3D 2/Gameplay/Schedule|Schedule]]&lt;br /&gt;
** [[Custom Maid 3D 2/Gameplay/Maid_Classes|Maid Classes]]&lt;br /&gt;
** [[Custom Maid 3D 2/Gameplay/H_Guide|H Guide]]&lt;br /&gt;
** [[Custom Maid 3D 2/Gameplay/Skills|Skills]]&lt;br /&gt;
** [[Custom Maid 3D 2/Gameplay/VIP_Events|VIP Events]]&lt;br /&gt;
** [[Custom Maid 3D 2/Gameplay/Trophy|Trophy]]&lt;br /&gt;
&lt;br /&gt;
* '''[[Custom Maid 3D 2/Modding|Modding]]'''&lt;br /&gt;
** [[Custom Maid 3D 2/Modding/ReiPatcher|Patching 101: How to ReiPatch for dummies]]&lt;br /&gt;
** [[Custom Maid 3D 2/Modding/Plugins|Writing plug-ins with ReiPatcher and UnityInjector]]&lt;br /&gt;
&lt;br /&gt;
* '''[[Custom Maid 3D 2/Version History|Version History]]'''&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/ReiPatcher&amp;diff=18877</id>
		<title>Custom Maid 3D2/Modding/ReiPatcher</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/ReiPatcher&amp;diff=18877"/>
				<updated>2015-09-27T00:00:23Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: Added new page: how to use ReiPatcher&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
[http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] is an awesome tool made by Hongfire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei]. ReiPatcher allows you to apply all kinds of modifications to a game that is made with Unity: you can change how game behaves; you can translate the game into another language; you can edit sounds, textures, models and other in-game assets while the game is running. All in all, the possibilities are limitless!&lt;br /&gt;
&lt;br /&gt;
If somebody linked you to this page, it means you're one of hundreds of people who cannot really understand how to use this neat tool. On the other hand, if you stumbled upon the page yourself, you most likely are seeking for an easy-to-understand tutorial on how to set up and use ReiPatcher. Whichever it might be, '''you came to the right place'''. By reading this small tutorial you will become a professional ReiPatcher'er(er?) in no time!&lt;br /&gt;
&lt;br /&gt;
What are we waiting for? Let the patching begin!&lt;br /&gt;
&lt;br /&gt;
== Grabbing the tools and getting it organized ==&lt;br /&gt;
Before we can start patching, we need ReiPatcher downloaded!&lt;br /&gt;
&lt;br /&gt;
Head to [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and grab the tool! Of course, remember to thank Rei-sama for his hard work by giving him some reputation '''[http://www.hongfire.com/forum/reputation.php?do=addreputation&amp;amp;p=3703144 here]''' (which is one of the many reasons you should join the greate Hongfire community!).&lt;br /&gt;
&lt;br /&gt;
After you have the archive downloaded, extract it to some folder. If you are asked to enter a password, it is most likely &amp;lt;code&amp;gt;byreisen&amp;lt;/code&amp;gt; (if it's not, check the maid thread).&lt;br /&gt;
&lt;br /&gt;
After you have extracted everything, you'll find '''at least''' the following files:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Filename !! Purpose and some other information&lt;br /&gt;
|-&lt;br /&gt;
| ExIni.dll || Used by ReiPatcher and the majority of user-created plug-ins. Responsible for creating, editing and saving configuration files.&lt;br /&gt;
|-&lt;br /&gt;
| ExIni.pdb and ExIni.xml || Mainly used by developers to debug and have a documentation of the ExIni library. If you are not a developer, you don't really need these.&lt;br /&gt;
|-&lt;br /&gt;
| Mono.Cecil.dll and other DLLs starting with Mono.Cecil || The most important tool of ReiPatcher that is responsible for patching the game.&lt;br /&gt;
|-&lt;br /&gt;
| ReiPatcher.exe || The executable you are going to run every time you want (or need) to patch a game.&lt;br /&gt;
|-&lt;br /&gt;
| ReiPatcher.pdb and ReiPatcher.xml || Just as for ExIni.pdb and .xml, they are mainly intended for the developers. You don't really need them unless you are a developer. It is, however, advised that you to keep ReiPatcher.pdb, as it will make it easier to read possible errors.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now move these files to some directory of your preference. The main point is that all the files stay together. The best place is perhaps the same directory where your games are located. Simply create a folder called ReiPatcher there and put the extracted files in it.&lt;br /&gt;
&lt;br /&gt;
There you go! Now let us test whether ReiPatcher works! Simply hold &amp;lt;code&amp;gt;Shift&amp;lt;/code&amp;gt; and rihgt-click on the empty space in ReiPatcher folder. From the context menu that has just appeared select &amp;lt;code&amp;gt;Open command window here&amp;lt;/code&amp;gt;. A command prompt should now open. The cursor (_) should be next to the ReiPatcher's directory. Write &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; and hit &amp;lt;code&amp;gt;Enter&amp;lt;/code&amp;gt;. If you copied (or moved) everything correctly, you'll get (almost similar) prompt:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ReiPatcher 0.9.0.8&lt;br /&gt;
 .NET Assembly Patcher - Powered by Mono.Cecil&lt;br /&gt;
 Copyright © Usagirei 2015&lt;br /&gt;
 GIT master [aac43ce754149cbde635f4ef6d5b164aa796fba1]&lt;br /&gt;
 ==============================================================                                 &lt;br /&gt;
 Switch Usage:&lt;br /&gt;
 -fc &amp;lt;Config&amp;gt;            Force creation of new configuration file&lt;br /&gt;
 -c &amp;lt;Config&amp;gt;             Use or create of configuration file &lt;br /&gt;
 -w              Waits for user input after patching&lt;br /&gt;
 -r              Reloads latest Assembly backup &lt;br /&gt;
 &lt;br /&gt;
 Exit Codes:&lt;br /&gt;
  0                      Success&lt;br /&gt;
  1                      NoPatchesApplied&lt;br /&gt;
 -3                      InternalException&lt;br /&gt;
 -2                      FileNotFound&lt;br /&gt;
 -1                      DirectoryNotFound&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You are all set! Now onto creating a game configuration!&lt;br /&gt;
&lt;br /&gt;
== Creating game configuration ==&lt;br /&gt;
Before patches can be applied, we need to create a configuration file that tells ReiPatcher where the game files are and where to find the patches to apply.&lt;br /&gt;
&lt;br /&gt;
If the game is officially supported by Hongfire community, you'll most likely find ready game configurations online. Most likely they are available on [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher's original thread].&lt;br /&gt;
&lt;br /&gt;
If, however you are in need to create a new configuration from scratch, simply open the console window in ReiPatcher's directory (by holding &amp;lt;code&amp;gt;Shift&amp;lt;/code&amp;gt;, right-clicking on the empty space in the folder and selecting &amp;lt;code&amp;gt;Open command window here&amp;lt;/code&amp;gt;) and type the following in the opened console window:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ReiPatcher.exe -fc &amp;lt;NAME&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where &amp;lt;NAME&amp;gt; is the name of the configuration (you're pretty much free to choose what it shall be).&lt;br /&gt;
&lt;br /&gt;
Whichever way you choose to obtain the configuration file, it should be put in the same folder as ReiPatcher.exe. That is not necessary, of course, but it will be A LOT easier to reference the files when patching through the command window.&lt;br /&gt;
&lt;br /&gt;
Now that you have the configuration file, let us examine it. Grab your favourite text editor of your choice (which should obviously be Notepad++, right? RIGHT?!) and open the configuration file you downloaded or created. Within you should see a bunch of (probably weird) syntax. Here's a quick agenda for you to remind/teach how to read .INI files:&lt;br /&gt;
* Lines starting with &amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt; are called comments. They are ignored by ExIni (for the exception the ones starting with &amp;lt;code&amp;gt;@&amp;lt;/code&amp;gt;. They are called environment variables and mostly used to load and store path information (which may change depending on the computer and game).&lt;br /&gt;
* Lines of the form &amp;lt;code&amp;gt;Variable=Value&amp;lt;/code&amp;gt; are variables that are used by ReiPatcher or other patchers. In ReiPatcher they are primarily used to store paths to different folders.&lt;br /&gt;
* Lines of the form &amp;lt;code&amp;gt;[Name]&amp;lt;/code&amp;gt; are called groups. They -- obviously -- group multiple variables together. All variables between two group names (or between a group name and the end of the file) belong to one group. The name of the grouped variables is defined in the upper group name declaration.&lt;br /&gt;
&lt;br /&gt;
After this crash-course into ExIni, here are some of the most important variables used by ReiPatcher. You'll most likely want to edit those to your liking:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Variable name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PatchesDir&amp;lt;/code&amp;gt; || Path to the patcher DLLs for this game configuration. Can be either absolute (ie. starting with drive letter) or relative (only folder name(s)). Depending on the game you'll want this to be &amp;lt;code&amp;gt;&amp;lt;GAME NAME&amp;gt;_Patches&amp;lt;/code&amp;gt;. Therefore you'll need to put plug-ins' patch DLLs in the folder called &amp;lt;code&amp;gt;&amp;lt;GAME NAME&amp;gt;_Patches&amp;lt;/code&amp;gt; that you must create in ReiPatcher folder.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; || Path to game assemblies that are to be patched. If you downloaded the configuration from the Internet, you'll most likely want to leave this as is. In other cases it is most likely of the form &amp;lt;code&amp;gt;&amp;lt;GAME DIRECTORY&amp;gt;\&amp;lt;GAME NAME&amp;gt;_Data\Managed&amp;lt;/code&amp;gt; (which, of course, might change depending on the game.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Executable&amp;lt;/code&amp;gt; || Set this to the path to the game executable, if you want ReiPatcher to launch the game after patching is complete. Leave empty if you don't.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Arguments&amp;lt;/code&amp;gt; || Additional arguments to use when launching the game.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Directory&amp;lt;/code&amp;gt; || Root of the game (the one that contains the game's executable).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Any additional values might vary depending on the patches and tools you use, which is why we shall not go deeper into the topic.&lt;br /&gt;
&lt;br /&gt;
After you have added your game configuration (and created the folder for patches as specified in the game configuration file), you can test/run it with ReiPatcher. Simply open the console window in ReiPatcher directory and type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ReiPatcher.exe -c &amp;lt;NAME&amp;gt;.ini&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where &amp;lt;NAME&amp;gt; is the name of your configuration file. If everything went well (and your folder containing the patches is empty), you should see the following output:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ReiPatcher 0.9.0.8&lt;br /&gt;
 .NET Assembly Patcher - Powered by Mono.Cecil&lt;br /&gt;
 Copyright © Usagirei 2015&lt;br /&gt;
 GIT master [aac43ce754149cbde635f4ef6d5b164aa796fba1]&lt;br /&gt;
 ==============================================================================&lt;br /&gt;
 Loading configuration file: 'CM3D2x64.ini'&lt;br /&gt;
 ============================== Loading Patchers ==============================&lt;br /&gt;
 Loading Patchers&lt;br /&gt;
 No Patches Found&lt;br /&gt;
 ================================= Pre-Patch ==================================&lt;br /&gt;
 ============================= Loading Assemblies =============================&lt;br /&gt;
 ================================== Patching ==================================&lt;br /&gt;
 ================================= Post-Patch =================================&lt;br /&gt;
 ================================== Finished ==================================&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Since we had no patches in the folder that we specified in the configuration file, no patches were applied! Let us now proceed to actually downloading installing the patches and actually applying them!&lt;br /&gt;
&lt;br /&gt;
== Installing the patches ==&lt;br /&gt;
We're almost there! The only step left is to apply the patches!&lt;br /&gt;
&lt;br /&gt;
Download the plug-ins of your choice and extract the downloaded archives.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, there are no strict rules on how to name either the folders in the archive or how to call the DLLs themselves. Therefore, '''always consult the README included with the plug-ins first!''' That being said, the most common way to divide the DLLs and other files in the plug-in is to divide them into three folders: &amp;lt;code&amp;gt;Manged&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ReiPatcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;UnityInjector&amp;lt;/code&amp;gt;. If that's the case, all you need to do is:&lt;br /&gt;
* Copy the contents of &amp;lt;code&amp;gt;Manged&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;Game directory&amp;gt;\&amp;lt;GAME&amp;gt;_Data\Managed&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;&amp;lt;Game directory&amp;gt;&amp;lt;/code&amp;gt; is the path to the game root (the directory where the game's extecutable is) and &amp;lt;code&amp;gt;&amp;lt;GAME&amp;gt;&amp;lt;/code&amp;gt; is the game code with the possible addition of some other codes, like CPU architecture.&lt;br /&gt;
* Copy the contents of &amp;lt;code&amp;gt;ReiPatcher&amp;lt;/code&amp;gt; to the patches folder specified in the game's configuration file.&lt;br /&gt;
* Copy the contents of &amp;lt;code&amp;gt;UnityInjector&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;Game directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt; if the folder does not exist yet, create it.&lt;br /&gt;
&lt;br /&gt;
Other times the developer doesn't bother to separate the DLLs into differenet folders. In these cases they most likely specify the purpose of the DLL by their name. Again, there are not strict rules on this either, but it seems that most developers name their plug-ins in the following manner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;GAME&amp;gt;.&amp;lt;Plugin name&amp;gt;.&amp;lt;Type&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In that case &amp;lt;code&amp;gt;&amp;lt;GAME&amp;gt;&amp;lt;/code&amp;gt; is the game code, &amp;lt;code&amp;gt;&amp;lt;Plugin name&amp;gt;&amp;lt;/code&amp;gt; is the name of the plug-in and &amp;lt;code&amp;gt;&amp;lt;Type&amp;gt;&amp;lt;/code&amp;gt; is the type of the DLL. Here are the most common type names and where to place the DLLs with that type:&lt;br /&gt;
* &amp;lt;code&amp;gt;Hook&amp;lt;/code&amp;gt; (also sometimes blank or &amp;lt;code&amp;gt;Core&amp;lt;/code&amp;gt;): put to &amp;lt;code&amp;gt;&amp;lt;Game directory&amp;gt;\&amp;lt;GAME&amp;gt;_Data\Managed&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;&amp;lt;Game directory&amp;gt;&amp;lt;/code&amp;gt; is the path to the game root (the directory where the game's extecutable is) and &amp;lt;code&amp;gt;&amp;lt;GAME&amp;gt;&amp;lt;/code&amp;gt; is the game code with the possible addition of some other codes, like CPU architecture.&lt;br /&gt;
* &amp;lt;code&amp;gt;Patch&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Patcher&amp;lt;/code&amp;gt;): Put to the patches folder specified in the game's configuration file.&lt;br /&gt;
* &amp;lt;code&amp;gt;Plugin&amp;lt;/code&amp;gt;: Put to &amp;lt;code&amp;gt;&amp;lt;Game directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt; if the folder does not exist yet, create it.&lt;br /&gt;
&lt;br /&gt;
=== The moment of truth ===&lt;br /&gt;
&lt;br /&gt;
When you have put everything into place, it is time to run ReiPatcher. Open command window in ReiPatcher folder and type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 ReiPatcher.exe -c &amp;lt;NAME&amp;gt;.ini&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where &amp;lt;NAME&amp;gt; is the name of your configuration file. If everything went well, you'll see the green text that specifies that every patch has been applied successfully. Horaay! Now you can enjoy your game with the new plug-ins!&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
We briefly discussed how to install ReiPatcher, how to create own game configurations and how to install and apply patches. Much information has been omitted for the sake of simplicity, but this tutorial serves as a nice crash-course into the world of Unity Engine patching.&lt;br /&gt;
&lt;br /&gt;
I hope that you, dear reader, have grasped the most essential knowledge of being a ReiPatcher'er(er?)(er??). Whenever you have issues with patching the game, always consult this tutorial or the original ReiPatcher thread (unless you will get linked back to this tutorial, that is -- in which case you have missed something very obvious).&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18213</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18213"/>
				<updated>2015-08-12T18:30:44Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: /* Summary */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Please note that owing to ever-so-evolving patching tools some parts of the tutorial may be outdated. The developers of said tools try their best to bring more features while trying to preserve the original programming routines. However, changes happen and the editors of this wiki attempt to update the documentation as fast as possible.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be almost impossible to manipulate, which is due to the code being mostly unmanaged (notice that the managed code is still compiled into CIL, albeit with &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt; tag.).&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
'''NOTE:''' Since ReiPatcherPlus 2.0, the library has undergone some major changes in structure. Therefore, note that some of parts of this page concerning ReiPatcherPlus might be outdated.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2(x84/x64)_Data\Managed&amp;lt;/code&amp;gt; folder at the very least.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Inspecting original code with a decompiler ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&amp;lt;/br&amp;gt;&lt;br /&gt;
'''Note:''' You can copy &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; as well, but remember that if you intend on using UnityInjector along with ReiPatcher, consider referencing the assembly directly from game directory instead. That way, after ReiPatcher had applied the patches, the IDE will automatically pick up updated method and visibility definitions.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming conventions ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, as of this moment, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. The hook DLL acts more often than not as a bridge between the game's own internal API and our plug-in code.&lt;br /&gt;
&lt;br /&gt;
If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good practice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies. &lt;br /&gt;
The patcher DLL is used by ReiPatcher to allow the plug-in developer to inject custom calls to the hook methods, change member field access and adding own code.&lt;br /&gt;
&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
Every assembly that one wishes to be patched must be requested. Otherwise it might not be included into the patching cycle.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times and on the right assemblies.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if our patch has already been applied to the specified assembly. That way we can avoid injecting the same code twice.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
The contents of the method depend on the situation. However, in almost all cases patching requires using various methods provided by Mono.Cecil to alter the contents of classes and methods.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps if we are to use pure Cecil and CIL:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, method search and injecting can be done easier with ReiPatcherPlus.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here are the main steps in using ReiPatcherPlus:&lt;br /&gt;
&lt;br /&gt;
'''1. Acquiring the type definitions'''&amp;lt;br/&amp;gt;&lt;br /&gt;
This is done simply with Mono.Cecil's &amp;lt;code&amp;gt;ModuleDefinition.GetType(string name)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
 TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''2. Getting the target method and the appropriate hook'''&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides an extension to Mono.Cecil: &amp;lt;code&amp;gt;TypeDefinition.GetMethod(string name)&amp;lt;/code&amp;gt; which searches for the first method with the given name.&amp;lt;br/&amp;gt;&lt;br /&gt;
Furthermore, to get a suiting hook method, we can use &amp;lt;code&amp;gt;GetHookMethod(MethodDefinition target, TypeDefinition hookType, string hookName, MethodFeatures features)&amp;lt;/code&amp;gt; which finds a suitable hook method that matches both the target method and the given criteria.&lt;br /&gt;
Since our hook method has only a parameter of the target type, only using the feature &amp;lt;code&amp;gt;MethodFeatures.PassTargetType&amp;lt;/code&amp;gt; will suffice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
 MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more detailed discussion on method features and &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, refer to the later sections.&lt;br /&gt;
&lt;br /&gt;
'''3. Injecting the code'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Having created an instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt;, we can now simply use ReiPatcherPlus's &amp;lt;code&amp;gt;AttachMethod(MethodHook hook, int codeOffset)&amp;lt;/code&amp;gt;. Since the hook method was searched with &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, one can be sure that the hook method is in fact injectable into the target method.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;int codeOffset&amp;lt;/code&amp;gt; specifies the index of the IL code to start the injection from. Since we want to add the hook at the beginning of the &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;, we simply pass 0:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 this.AttachMethod(hookMethod, 0);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putting it all together we get a fancy patch method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Get type definitions for the UIButton and the hook class&lt;br /&gt;
     TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
     TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
     // Get the method definition for OnClick and OnClickHook&lt;br /&gt;
     // GetHookMethod assures that the created MethodHook instance contains a valid hook for OnClick&lt;br /&gt;
     MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
     MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
     &lt;br /&gt;
     // Passing 0 will inject the hook method at the beginning of OnClick method&lt;br /&gt;
     this.AttachMethod(hookMethod, 0);&lt;br /&gt;
     &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Box1 start}}&lt;br /&gt;
'''NOTE:''' The alternative below is listed only for legacy reasons. ReiPatcherPlus 2.0+ marks &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; as obsolete. Consider using the above-mentioned code.&lt;br /&gt;
{{Boxes end}}&lt;br /&gt;
&lt;br /&gt;
Alternatively, ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
             TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
             &lt;br /&gt;
             MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
             MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
             &lt;br /&gt;
             this.AttachMethod(hookMethod, 0);&lt;br /&gt;
             &lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL (using UnityInjector) ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehaviour&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that the name of plug-in's INI configuration file will be the same as plug-in class name. In our case, calling &amp;lt;code&amp;gt;SaveConfig()&amp;lt;/code&amp;gt; will create a configuration file named &amp;lt;code&amp;gt;HelloWorldPlugin.ini&amp;lt;/code&amp;gt; which will be saved to &amp;lt;code&amp;gt;&amp;lt;Game's main directory&amp;gt;\UnityInjector\Config&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command below&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Source code and example projects ==&lt;br /&gt;
Below is a list of different projects written for ReiPatcher and UnityInjector. The projects can be used as templates for own projects.&lt;br /&gt;
* [https://github.com/usagirei/CM3D2_CameraControlEx Extended Camera Control] by [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei]&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
In the examples we shall use the following class that contains potential methods to hook:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         protected enum SwallowType&lt;br /&gt;
         {&lt;br /&gt;
             European,&lt;br /&gt;
             African&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
         private float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public float GetNeededSwallows(float distance);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         public static T FirstSwallow&amp;lt;T&amp;gt;(List&amp;lt;T&amp;gt; swallows);&lt;br /&gt;
         public static T FirstSwallow&amp;lt;T&amp;gt;(List&amp;lt;T&amp;gt; swallows, T addition);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting methods and fields ===&lt;br /&gt;
ReiPatcherPlus adds two new extension methods to Mono.Cecil that allow to locate method definitions in their respected types.&lt;br /&gt;
Those methods are added as extensions to &amp;lt;code&amp;gt;Mono.Cecil.TypeDefinition&amp;lt;/code&amp;gt; type.&amp;lt;br/&amp;gt;&lt;br /&gt;
Those two methods are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodDefinition GetMethod(string methodName);&lt;br /&gt;
 MethodDefinition GetMethod(string methodName, params TypeReference[] paramTypes);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;methodName&amp;lt;/code&amp;gt; || Name of the method to search for.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;paramTypes&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;TypeReference&amp;lt;/code&amp;gt; representation of method parameters. Used to search for the exact overload of a method.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Furthermore, one can easily acquire member fields (delegates, variables) of the type. That is done with the method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 FieldDefinition GetField(string memberName);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where &amp;lt;code&amp;gt;memberName&amp;lt;/code&amp;gt; is name of the member to search for.&lt;br /&gt;
&lt;br /&gt;
In both cases, the methods will return &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;, if the fitting method/field has not been found. Therefore, it is up to the developer to make sure the provided parameters point to a valid method or field. &lt;br /&gt;
In some cases, the programmer may need to perform null checking.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Will return GetNeededSwallows(int)&lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Will return GetNeededSwallows(float)&lt;br /&gt;
 MethodDefinition m2 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;, Parameter.FromType&amp;lt;float&amp;gt;());&lt;br /&gt;
 &lt;br /&gt;
 FieldDefinition f1 = swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Handling parameters ===&lt;br /&gt;
To make turning &amp;lt;code&amp;gt;System.Type&amp;lt;/code&amp;gt; and normal type declarations into dummy &amp;lt;code&amp;gt;TypeReference&amp;lt;/code&amp;gt;s to use with ReiPatcherPlus, &amp;lt;code&amp;gt;Parameter&amp;lt;/code&amp;gt; class was created.&lt;br /&gt;
The class houses a panoply of useful methods to create &amp;quot;dummy type references&amp;quot; (they are not actual references to the real types -- instead, they are containers for type information used method search methods).&amp;lt;br/&amp;gt;&lt;br /&gt;
Such methods are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeReference FromType(Type type, params string[] genericTypeNames);&lt;br /&gt;
 TypeReference FromType&amp;lt;T&amp;gt;();&lt;br /&gt;
 TypeReference FromTypeRef(Type type, params string[] genericTypeNames);&lt;br /&gt;
 &lt;br /&gt;
 TypeReference CreateGeneric(string name);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the first four methods, the parameter descriptions are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;System.Type&amp;lt;/code&amp;gt; representation of the given type. Can be acquired with &amp;lt;code&amp;gt;typeof(TypeName)&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;genericTypeNames&amp;lt;/code&amp;gt; || Names of the generic types. Used only, if the provided &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; has undefined generic parameters.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; || Type name of the type to be converted. Calling &amp;lt;code&amp;gt;FromType&amp;lt;T&amp;gt;()&amp;lt;/code&amp;gt; has the same effect as &amp;lt;code&amp;gt;FromType(typeof(T))&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
As for &amp;lt;code&amp;gt;CreateGeneric&amp;lt;/code&amp;gt;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; || Name of the generic type to create.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note that in order for &amp;lt;code&amp;gt;GetMethod&amp;lt;/code&amp;gt; to succeed with generic types, the names of those must stay the same. If the original method had a generic type &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;, one must make the type with &amp;lt;code&amp;gt;Parameter.MakeGeneric(&amp;quot;T&amp;quot;)&amp;lt;/code&amp;gt; in order for the method to be found.&lt;br /&gt;
The same principle must hold when matching target method parameters with the hook method parameters.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // t1 and t2 are technically the same &lt;br /&gt;
 TypeReference t1 = Parameter.FromType(typeof(int));&lt;br /&gt;
 TypeReference t2 = Parameter.FromType&amp;lt;int&amp;gt;();&lt;br /&gt;
 &lt;br /&gt;
 // Creates a type of List&amp;lt;T&amp;gt;&lt;br /&gt;
 TypeReference t3 = Parameter.FromType(typeof(List&amp;lt;&amp;gt;), &amp;quot;T&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Creates a reference type System.Boolean&amp;amp;&lt;br /&gt;
 TypeReference t4 = Parameter.FromTypeRef(typeof(bool));&lt;br /&gt;
 &lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m3 = swallowType.GetMethod(&amp;quot;MakeFly&amp;quot;, Parameter.FromType&amp;lt;bool&amp;gt;(), Parameter.FromType&amp;lt;float&amp;gt;());&lt;br /&gt;
 MethodDefinition m4 = swallowType.GetMethod(&amp;quot;FirstSwallow&amp;quot;, Parameter.FromType(typeof(List&amp;lt;&amp;gt;), &amp;quot;T&amp;quot;), Parameter.CreateGeneric(&amp;quot;T&amp;quot;));&lt;br /&gt;
 &lt;br /&gt;
 // WILL NOT WORK: The provided generic types differ from the original definition&lt;br /&gt;
 MethodDefinition m5 = swallowType.GetMethod(&amp;quot;FirstSwallow&amp;quot;, Parameter.FromType(typeof(List&amp;lt;&amp;gt;),&amp;quot;A&amp;quot;), Parameter.CreateGeneric(&amp;quot;G&amp;quot;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The MethodHook type and getting hooks ===&lt;br /&gt;
To provide an easy patching experience, ReiPatcherPlus includes &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; container that exposes the following get-only properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Hook&amp;lt;/code&amp;gt; || Method definition of the hook method. Will be hooked to the target.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Features&amp;lt;/code&amp;gt; || Additional criteria by which the hook method was chosen. Refer to the next subsection for more information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Target&amp;lt;/code&amp;gt; || Method definition of the method to hook (target method).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The creation of the &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; instance is controlled internally from ReiPatcherPlus. That way the library guarantees that the specified hook-target pair is valid and injectable.&lt;br /&gt;
&lt;br /&gt;
Currently there are two ways of getting the instance: by using &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; extension &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt; or by calling &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The exact definitions are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodHook GetHookMethod(MethodDefinition target, &lt;br /&gt;
                          TypeDefinition hookType, &lt;br /&gt;
                          string hookName, &lt;br /&gt;
                          MethodFeatures features, &lt;br /&gt;
                          params FieldDefinition[] memberReferences);&lt;br /&gt;
 &lt;br /&gt;
 MethodHook MethodHook.FromMethodDefinition(MethodDefinition target, &lt;br /&gt;
                                            MethodDefinition hook, &lt;br /&gt;
                                            MethodFeatures features, &lt;br /&gt;
                                            params FieldDefinition[] memberReferences);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The parameter description is the following:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;target&amp;lt;/code&amp;gt; || The method definition of the method which is to be hooked.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || The type (class/struct) that possesses the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; || The criteria by which the hook method should be chosen. Defines the structure of the hook method. Refer to the next subsection for more information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memberReferences&amp;lt;/code&amp;gt; || If one of the criteria is &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt;, specifies the fields that are to be passed to the method.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;hook&amp;lt;/code&amp;gt; || Method definition of the hook method.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
While using the methods, note the following:&lt;br /&gt;
* When using &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, the final &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; might be different from the ones specified. That is simply because the method adapts to its passed parameters to find the best hook method.&lt;br /&gt;
However, the method attempts to find the best hook without throwing any exceptions (for the exception of &amp;lt;code&amp;gt;ArgumentException&amp;lt;/code&amp;gt; if the provided member fields do not belong to the target type).&lt;br /&gt;
* &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt; strictly checks whether the provided target and hook are injectable. If a discrepancy is found, the method will throw an exception containing the reason the method failed.&lt;br /&gt;
* Prefer using &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, as it mostly exception-free and will return either a working instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Method Features ====&lt;br /&gt;
To allow the developer to freely choose which kind of hook to use, what parameters to pass and what to return, ReiPatcherPlus allows to specify certain criteria that define the layot of the hook method.&lt;br /&gt;
Albeit allowing different set of parameters to be passed, the hook method must have its parameters in a certain order for ReiPatcherPlus to work with them.&lt;br /&gt;
&lt;br /&gt;
Below is the hook method template with numbered positions and a table of what types are allowed in place of those positions and which &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; fields to use to enable those positions:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static &amp;lt;2.1&amp;gt; MyHookMethod(&amp;lt;1&amp;gt;, &amp;lt;2.2&amp;gt;, &amp;lt;3&amp;gt;, &amp;lt;4&amp;gt;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; field !! Position value replacement, if feature specified (only types and prefixes specified) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.None&amp;lt;/code&amp;gt; || &amp;lt;1&amp;gt;, &amp;lt;2.2&amp;gt;, &amp;lt;3&amp;gt;, &amp;lt;4&amp;gt; = Empty&amp;lt;br/&amp;gt;&amp;lt;2.1&amp;gt; = &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || The method may not have any of the features.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassTargetType&amp;lt;/code&amp;gt; || &amp;lt;1&amp;gt; = Target type || The method may be passed a reference to the target type that initially called the hooked method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; || &amp;lt;2.1&amp;gt; = &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;If target has a return type:&amp;lt;br/&amp;gt;&amp;lt;2.2&amp;gt; = &amp;lt;code&amp;gt;out &amp;lt;return type&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;Otherwise:&amp;lt;br/&amp;gt;&amp;lt;2.2&amp;gt; = Empty || The hook method is a redirect and thus may be passed a reference to the return value (if there is such). If the the target method has a return value of type &amp;lt;code&amp;gt;&amp;lt;return type&amp;gt;&amp;lt;/code&amp;gt;, a parameter of the same type is passed as a reference to the hook method.&amp;lt;br/&amp;gt;'''Note:''' If the feature is not specified, &amp;lt;2.1&amp;gt; must be &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt; || &amp;lt;3&amp;gt; = &amp;lt;code&amp;gt;ref &amp;lt;type1&amp;gt;, ref &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass references to the target type's member fields (assuming target method is not static) specified by the &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; creation method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMethodParametersByValue&amp;lt;/code&amp;gt; || &amp;lt;4&amp;gt; = &amp;lt;code&amp;gt;&amp;lt;type1&amp;gt;, &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass its own parameters to the hook. Since they are passed by value, they cannot be altered.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMethodParametersByReference&amp;lt;/code&amp;gt; || &amp;lt;4&amp;gt; = &amp;lt;code&amp;gt;ref &amp;lt;type1&amp;gt;, ref &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass its own parameters to the hook. Since they are passed by reference, they can be altered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Some important things to point out:&lt;br /&gt;
* The hook method '''must''' be public and static! Otherwise it is impossible to hook it anywhere.&lt;br /&gt;
* Some of the above-mentioned features can be left out. However the order of the parameters must be always preserved!&lt;br /&gt;
* If &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; is set, the hook method must return a &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the hook method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the execution of the original target method's instructions is interrupted; the target method simply returns the result value it got from the hook method (if any). In the contrary, if the hook method return &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the original target method will continue its execution after the hook method has completed executing its instructions.&lt;br /&gt;
* Legacy notice: &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; makes ReiPatcherPlus search for a redirect method. However, since both hooking and redirecting have been combined into one single method, there is no point in differentiating between them anymore.&lt;br /&gt;
&lt;br /&gt;
The features may be combined with a logical OR operator (&amp;lt;code&amp;gt;|&amp;lt;/code&amp;gt;). In addition to the features above, the &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; enumeration has the following feature combinations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Feature !! Combination equivalent&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.All_ByValue&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;MethodFeatures.PassTargetType | MethodFeatures.PassReturn | MethodFeatures.PassMemberReferences | MethodFeatures.PassMethodParametersByValue&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.All_ByReference&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;MethodFeatures.PassTargetType | MethodFeatures.PassReturn | MethodFeatures.PassMemberReferences | MethodFeatures.PassMethodParametersByReference&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 // Getting type definition for the class that contains all the hook methods&lt;br /&gt;
 TypeDefinition hookType = HookModule.GetType(&amp;quot;MyHookNamespace.Hook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 MethodDefinition m2 = swallowType.GetMethod(&amp;quot;MakeFly&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
 // Valid hook method prototype: public static void GetNeededSwallowsHook1()&lt;br /&gt;
 MethodHook hookM1 = this.GetHookMethod(m1, &lt;br /&gt;
                                        hookType, &lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook1&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.None);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool GetNeededSwallowsHook2(Swallow self, out float result, int coconuts)&lt;br /&gt;
 MethodHook hookM2 = this.GetHookMethod(m1,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook2&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByValue);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool GetNeededSwallowsHook3(Swallow self, out float result, ref int coconuts)									&lt;br /&gt;
 MethodHook hookM3 = this.GetHookMethod(m1,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook3&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByReference);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool MakeFlyHook(Swallow self, out float result, ref float airSpeedVelocity, int coconuts)									&lt;br /&gt;
 MethodHook hookM4 = this.GetHookMethod(m2,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;MakeFlyHook&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMemberReferences&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByValue,&lt;br /&gt;
                                        swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;));&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition hookMethod = hookType.GetMethod(&amp;quot;MakeFlyHook2&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool MakeFlyHook(Swallow self, out float result, ref float airSpeedVelocity, ref int coconuts)									&lt;br /&gt;
 MethodHook hookM5 = MethodHook.FromMethodDefinition(m2,&lt;br /&gt;
                                                     hookMethod,&lt;br /&gt;
                                                     MethodFeatures.All_ByReference,&lt;br /&gt;
                                                     swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Injecting the methods ===&lt;br /&gt;
Finally, ReiPatcherPlus provides a functionality to patch methods. That can be done with &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
The exact definitions and parameter descriptions are below:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void AttachMethod(MethodHook hook, int codeOffset);&lt;br /&gt;
 void AttachMethod(MethodDefinition target, &lt;br /&gt;
                   MethodDefinition hook, &lt;br /&gt;
                   int codeOffset, &lt;br /&gt;
                   MethodFeatures features,&lt;br /&gt;
                   params FieldDefinition[] memberReferences);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;target&amp;lt;/code&amp;gt; || The method definition of the method which is to be hooked.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodDefinition hook&amp;lt;/code&amp;gt; || Method definition of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; || The criteria by which the hook method should be chosen. Defines the structure of the hook method. '''Default: ''' &amp;lt;code&amp;gt;MethodFeatures.None&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memberReferences&amp;lt;/code&amp;gt; || If one of the criteria is &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt;, specifies the fields that are to be passed to the method.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;MethodHook hook&amp;lt;/code&amp;gt; || An instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; that contains all the appropriate information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;codeOffset&amp;lt;/code&amp;gt; || An index value of an IL instruction in the target method from which to begin injection. If set to negative, will begin counting from the last instruction of the target method, where -1 is being the last instruction.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Elementary, these two methods will automatically inject the needed CIL instructions depending on the chosen hook/target method.&amp;lt;br/&amp;gt;&lt;br /&gt;
The latter method will verify the compatibility between the target and the hook before applying the patch. That method is equivalent to calling &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt; and then &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Most of the time setting code offset to 0 will be sufficient for plug-ins. However, if one wants to place the hook at a certain place, refer to the previous sections on how to decompile the .NET code. Most of the decompilers come with IL decompilers bundled (like ILSpy), which allows to inspect pure IL instructions to find the perfect attachment point.&lt;br /&gt;
&lt;br /&gt;
Note as well that &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt; will always add its own CIL instructions '''before''' the specified code offset! That is done to prevent the developers from inserting method hooks after the &amp;lt;code&amp;gt;ret&amp;lt;/code&amp;gt; instruction that is always present as a last IL instruction in every method. Any code insterted after the said instruction is simply neglected by the machine.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 TypeDefinition hookType = HookModule.GetType(&amp;quot;MyHookNamespace.Hook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method prototype: public static void GetNeededSwallowsHook1()&lt;br /&gt;
 MethodHook hookM1 = this.GetHookMethod(m1, &lt;br /&gt;
                                        hookType, &lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook1&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.None);&lt;br /&gt;
 &lt;br /&gt;
 this.AttachMethod(hookM1, 0);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Debugging functions ===&lt;br /&gt;
ReiPatcherPlus provides simple methods for patcher message logging. All of the logging methods are located in &amp;lt;code&amp;gt;RPPLogger&amp;lt;/code&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
However, to enable logging, one must use the DEV version of the ReiPatcherPlus (slightly larger file size than normal ReiPatcherPlus).&lt;br /&gt;
After that, one can set &amp;lt;code&amp;gt;RPPLogger.VERBOSE_LEVEL&amp;lt;/code&amp;gt; variable to enable logging of certain methods.&lt;br /&gt;
&lt;br /&gt;
Possible variable values are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.None&amp;lt;/code&amp;gt; || Don't output any messages&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.Patcher&amp;lt;/code&amp;gt; || Output patcher-related messages (getting hook methods, attaching methods, etc.).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.Cecil&amp;lt;/code&amp;gt; || Output Mono.Cecil-related extension method messages. Includes parameter equality checking and method searching.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The flags can be combined with a logical OR (&amp;lt;code&amp;gt;|&amp;lt;/code&amp;gt;) operator.&lt;br /&gt;
&lt;br /&gt;
If one whishes to output own logging messages, it is possible through the following methods located in &amp;lt;code&amp;gt;RPPLogger&amp;gt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void Log(string message, VerboseLevel level, bool addPrefix);&lt;br /&gt;
 void LogLine(string message, VerboseLevel level, bool addPrefix);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the parameters:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt; || Message to output.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; || The level to output the message to. Used to filter the output based on selected levels.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;addPrefix&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will append a prefix specified on &amp;lt;code&amp;gt;RPPLogger.PREFIX&amp;lt;/code&amp;gt; before the specified &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The difference between the methods is that the latter will add a line break to the message, while the former one will not.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Set verbose level to patcher only&lt;br /&gt;
 RPPLogger.VERBOSE_LEVEL = RPPLogger.VerboseLevel.Patcher;&lt;br /&gt;
 &lt;br /&gt;
 // Will be shown in ReiPatcher console&lt;br /&gt;
 RPPLogger.LogLine(&amp;quot;Hello, log!&amp;quot;, RPPLogger.VerboseLevel.Patcher);&lt;br /&gt;
 &lt;br /&gt;
 // Won't be seen in ReiPatcher&lt;br /&gt;
 RPPLogger.LogLine(&amp;quot;I am hidden!&amp;quot;, RPPLogger.VerboseLevel.Cecil);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Legacy and other obsolete methods ===&lt;br /&gt;
These methods are marked as obsolete and must not be used. Instead, use the newer functionality of ReiPatcherPlus.&lt;br /&gt;
&lt;br /&gt;
==== Method hooking ====&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Method redirecting ====&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18212</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18212"/>
				<updated>2015-08-12T16:21:25Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: /* Injecting the methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Please note that owing to ever-so-evolving patching tools some parts of the tutorial may be outdated. The developers of said tools try their best to bring more features while trying to preserve the original programming routines. However, changes happen and the editors of this wiki attempt to update the documentation as fast as possible.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be almost impossible to manipulate, which is due to the code being mostly unmanaged (notice that the managed code is still compiled into CIL, albeit with &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt; tag.).&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
'''NOTE:''' Since ReiPatcherPlus 2.0, the library has undergone some major changes in structure. Therefore, note that some of parts of this page concerning ReiPatcherPlus might be outdated.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2(x84/x64)_Data\Managed&amp;lt;/code&amp;gt; folder at the very least.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Inspecting original code with a decompiler ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&amp;lt;/br&amp;gt;&lt;br /&gt;
'''Note:''' You can copy &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; as well, but remember that if you intend on using UnityInjector along with ReiPatcher, consider referencing the assembly directly from game directory instead. That way, after ReiPatcher had applied the patches, the IDE will automatically pick up updated method and visibility definitions.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming conventions ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, as of this moment, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. The hook DLL acts more often than not as a bridge between the game's own internal API and our plug-in code.&lt;br /&gt;
&lt;br /&gt;
If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good practice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies. &lt;br /&gt;
The patcher DLL is used by ReiPatcher to allow the plug-in developer to inject custom calls to the hook methods, change member field access and adding own code.&lt;br /&gt;
&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
Every assembly that one wishes to be patched must be requested. Otherwise it might not be included into the patching cycle.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times and on the right assemblies.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if our patch has already been applied to the specified assembly. That way we can avoid injecting the same code twice.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
The contents of the method depend on the situation. However, in almost all cases patching requires using various methods provided by Mono.Cecil to alter the contents of classes and methods.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps if we are to use pure Cecil and CIL:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, method search and injecting can be done easier with ReiPatcherPlus.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here are the main steps in using ReiPatcherPlus:&lt;br /&gt;
&lt;br /&gt;
'''1. Acquiring the type definitions'''&amp;lt;br/&amp;gt;&lt;br /&gt;
This is done simply with Mono.Cecil's &amp;lt;code&amp;gt;ModuleDefinition.GetType(string name)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
 TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''2. Getting the target method and the appropriate hook'''&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides an extension to Mono.Cecil: &amp;lt;code&amp;gt;TypeDefinition.GetMethod(string name)&amp;lt;/code&amp;gt; which searches for the first method with the given name.&amp;lt;br/&amp;gt;&lt;br /&gt;
Furthermore, to get a suiting hook method, we can use &amp;lt;code&amp;gt;GetHookMethod(MethodDefinition target, TypeDefinition hookType, string hookName, MethodFeatures features)&amp;lt;/code&amp;gt; which finds a suitable hook method that matches both the target method and the given criteria.&lt;br /&gt;
Since our hook method has only a parameter of the target type, only using the feature &amp;lt;code&amp;gt;MethodFeatures.PassTargetType&amp;lt;/code&amp;gt; will suffice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
 MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more detailed discussion on method features and &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, refer to the later sections.&lt;br /&gt;
&lt;br /&gt;
'''3. Injecting the code'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Having created an instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt;, we can now simply use ReiPatcherPlus's &amp;lt;code&amp;gt;AttachMethod(MethodHook hook, int codeOffset)&amp;lt;/code&amp;gt;. Since the hook method was searched with &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, one can be sure that the hook method is in fact injectable into the target method.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;int codeOffset&amp;lt;/code&amp;gt; specifies the index of the IL code to start the injection from. Since we want to add the hook at the beginning of the &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;, we simply pass 0:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 this.AttachMethod(hookMethod, 0);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putting it all together we get a fancy patch method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Get type definitions for the UIButton and the hook class&lt;br /&gt;
     TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
     TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
     // Get the method definition for OnClick and OnClickHook&lt;br /&gt;
     // GetHookMethod assures that the created MethodHook instance contains a valid hook for OnClick&lt;br /&gt;
     MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
     MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
     &lt;br /&gt;
     // Passing 0 will inject the hook method at the beginning of OnClick method&lt;br /&gt;
     this.AttachMethod(hookMethod, 0);&lt;br /&gt;
     &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Box1 start}}&lt;br /&gt;
'''NOTE:''' The alternative below is listed only for legacy reasons. ReiPatcherPlus 2.0+ marks &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; as obsolete. Consider using the above-mentioned code.&lt;br /&gt;
{{Boxes end}}&lt;br /&gt;
&lt;br /&gt;
Alternatively, ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
             TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
             &lt;br /&gt;
             MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
             MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
             &lt;br /&gt;
             this.AttachMethod(hookMethod, 0);&lt;br /&gt;
             &lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL (using UnityInjector) ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehaviour&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that the name of plug-in's INI configuration file will be the same as plug-in class name. In our case, calling &amp;lt;code&amp;gt;SaveConfig()&amp;lt;/code&amp;gt; will create a configuration file named &amp;lt;code&amp;gt;HelloWorldPlugin.ini&amp;lt;/code&amp;gt; which will be saved to &amp;lt;code&amp;gt;&amp;lt;Game's main directory&amp;gt;\UnityInjector\Config&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command below&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
In the examples we shall use the following class that contains potential methods to hook:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         protected enum SwallowType&lt;br /&gt;
         {&lt;br /&gt;
             European,&lt;br /&gt;
             African&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
         private float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public float GetNeededSwallows(float distance);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         public static T FirstSwallow&amp;lt;T&amp;gt;(List&amp;lt;T&amp;gt; swallows);&lt;br /&gt;
         public static T FirstSwallow&amp;lt;T&amp;gt;(List&amp;lt;T&amp;gt; swallows, T addition);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting methods and fields ===&lt;br /&gt;
ReiPatcherPlus adds two new extension methods to Mono.Cecil that allow to locate method definitions in their respected types.&lt;br /&gt;
Those methods are added as extensions to &amp;lt;code&amp;gt;Mono.Cecil.TypeDefinition&amp;lt;/code&amp;gt; type.&amp;lt;br/&amp;gt;&lt;br /&gt;
Those two methods are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodDefinition GetMethod(string methodName);&lt;br /&gt;
 MethodDefinition GetMethod(string methodName, params TypeReference[] paramTypes);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;methodName&amp;lt;/code&amp;gt; || Name of the method to search for.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;paramTypes&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;TypeReference&amp;lt;/code&amp;gt; representation of method parameters. Used to search for the exact overload of a method.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Furthermore, one can easily acquire member fields (delegates, variables) of the type. That is done with the method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 FieldDefinition GetField(string memberName);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where &amp;lt;code&amp;gt;memberName&amp;lt;/code&amp;gt; is name of the member to search for.&lt;br /&gt;
&lt;br /&gt;
In both cases, the methods will return &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;, if the fitting method/field has not been found. Therefore, it is up to the developer to make sure the provided parameters point to a valid method or field. &lt;br /&gt;
In some cases, the programmer may need to perform null checking.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Will return GetNeededSwallows(int)&lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Will return GetNeededSwallows(float)&lt;br /&gt;
 MethodDefinition m2 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;, Parameter.FromType&amp;lt;float&amp;gt;());&lt;br /&gt;
 &lt;br /&gt;
 FieldDefinition f1 = swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Handling parameters ===&lt;br /&gt;
To make turning &amp;lt;code&amp;gt;System.Type&amp;lt;/code&amp;gt; and normal type declarations into dummy &amp;lt;code&amp;gt;TypeReference&amp;lt;/code&amp;gt;s to use with ReiPatcherPlus, &amp;lt;code&amp;gt;Parameter&amp;lt;/code&amp;gt; class was created.&lt;br /&gt;
The class houses a panoply of useful methods to create &amp;quot;dummy type references&amp;quot; (they are not actual references to the real types -- instead, they are containers for type information used method search methods).&amp;lt;br/&amp;gt;&lt;br /&gt;
Such methods are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeReference FromType(Type type, params string[] genericTypeNames);&lt;br /&gt;
 TypeReference FromType&amp;lt;T&amp;gt;();&lt;br /&gt;
 TypeReference FromTypeRef(Type type, params string[] genericTypeNames);&lt;br /&gt;
 &lt;br /&gt;
 TypeReference CreateGeneric(string name);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the first four methods, the parameter descriptions are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;System.Type&amp;lt;/code&amp;gt; representation of the given type. Can be acquired with &amp;lt;code&amp;gt;typeof(TypeName)&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;genericTypeNames&amp;lt;/code&amp;gt; || Names of the generic types. Used only, if the provided &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; has undefined generic parameters.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; || Type name of the type to be converted. Calling &amp;lt;code&amp;gt;FromType&amp;lt;T&amp;gt;()&amp;lt;/code&amp;gt; has the same effect as &amp;lt;code&amp;gt;FromType(typeof(T))&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
As for &amp;lt;code&amp;gt;CreateGeneric&amp;lt;/code&amp;gt;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; || Name of the generic type to create.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note that in order for &amp;lt;code&amp;gt;GetMethod&amp;lt;/code&amp;gt; to succeed with generic types, the names of those must stay the same. If the original method had a generic type &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;, one must make the type with &amp;lt;code&amp;gt;Parameter.MakeGeneric(&amp;quot;T&amp;quot;)&amp;lt;/code&amp;gt; in order for the method to be found.&lt;br /&gt;
The same principle must hold when matching target method parameters with the hook method parameters.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // t1 and t2 are technically the same &lt;br /&gt;
 TypeReference t1 = Parameter.FromType(typeof(int));&lt;br /&gt;
 TypeReference t2 = Parameter.FromType&amp;lt;int&amp;gt;();&lt;br /&gt;
 &lt;br /&gt;
 // Creates a type of List&amp;lt;T&amp;gt;&lt;br /&gt;
 TypeReference t3 = Parameter.FromType(typeof(List&amp;lt;&amp;gt;), &amp;quot;T&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Creates a reference type System.Boolean&amp;amp;&lt;br /&gt;
 TypeReference t4 = Parameter.FromTypeRef(typeof(bool));&lt;br /&gt;
 &lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m3 = swallowType.GetMethod(&amp;quot;MakeFly&amp;quot;, Parameter.FromType&amp;lt;bool&amp;gt;(), Parameter.FromType&amp;lt;float&amp;gt;());&lt;br /&gt;
 MethodDefinition m4 = swallowType.GetMethod(&amp;quot;FirstSwallow&amp;quot;, Parameter.FromType(typeof(List&amp;lt;&amp;gt;), &amp;quot;T&amp;quot;), Parameter.CreateGeneric(&amp;quot;T&amp;quot;));&lt;br /&gt;
 &lt;br /&gt;
 // WILL NOT WORK: The provided generic types differ from the original definition&lt;br /&gt;
 MethodDefinition m5 = swallowType.GetMethod(&amp;quot;FirstSwallow&amp;quot;, Parameter.FromType(typeof(List&amp;lt;&amp;gt;),&amp;quot;A&amp;quot;), Parameter.CreateGeneric(&amp;quot;G&amp;quot;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The MethodHook type and getting hooks ===&lt;br /&gt;
To provide an easy patching experience, ReiPatcherPlus includes &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; container that exposes the following get-only properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Hook&amp;lt;/code&amp;gt; || Method definition of the hook method. Will be hooked to the target.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Features&amp;lt;/code&amp;gt; || Additional criteria by which the hook method was chosen. Refer to the next subsection for more information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Target&amp;lt;/code&amp;gt; || Method definition of the method to hook (target method).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The creation of the &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; instance is controlled internally from ReiPatcherPlus. That way the library guarantees that the specified hook-target pair is valid and injectable.&lt;br /&gt;
&lt;br /&gt;
Currently there are two ways of getting the instance: by using &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; extension &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt; or by calling &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The exact definitions are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodHook GetHookMethod(MethodDefinition target, &lt;br /&gt;
                          TypeDefinition hookType, &lt;br /&gt;
                          string hookName, &lt;br /&gt;
                          MethodFeatures features, &lt;br /&gt;
                          params FieldDefinition[] memberReferences);&lt;br /&gt;
 &lt;br /&gt;
 MethodHook MethodHook.FromMethodDefinition(MethodDefinition target, &lt;br /&gt;
                                            MethodDefinition hook, &lt;br /&gt;
                                            MethodFeatures features, &lt;br /&gt;
                                            params FieldDefinition[] memberReferences);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The parameter description is the following:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;target&amp;lt;/code&amp;gt; || The method definition of the method which is to be hooked.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || The type (class/struct) that possesses the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; || The criteria by which the hook method should be chosen. Defines the structure of the hook method. Refer to the next subsection for more information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memberReferences&amp;lt;/code&amp;gt; || If one of the criteria is &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt;, specifies the fields that are to be passed to the method.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;hook&amp;lt;/code&amp;gt; || Method definition of the hook method.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
While using the methods, note the following:&lt;br /&gt;
* When using &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, the final &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; might be different from the ones specified. That is simply because the method adapts to its passed parameters to find the best hook method.&lt;br /&gt;
However, the method attempts to find the best hook without throwing any exceptions (for the exception of &amp;lt;code&amp;gt;ArgumentException&amp;lt;/code&amp;gt; if the provided member fields do not belong to the target type).&lt;br /&gt;
* &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt; strictly checks whether the provided target and hook are injectable. If a discrepancy is found, the method will throw an exception containing the reason the method failed.&lt;br /&gt;
* Prefer using &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, as it mostly exception-free and will return either a working instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Method Features ====&lt;br /&gt;
To allow the developer to freely choose which kind of hook to use, what parameters to pass and what to return, ReiPatcherPlus allows to specify certain criteria that define the layot of the hook method.&lt;br /&gt;
Albeit allowing different set of parameters to be passed, the hook method must have its parameters in a certain order for ReiPatcherPlus to work with them.&lt;br /&gt;
&lt;br /&gt;
Below is the hook method template with numbered positions and a table of what types are allowed in place of those positions and which &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; fields to use to enable those positions:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static &amp;lt;2.1&amp;gt; MyHookMethod(&amp;lt;1&amp;gt;, &amp;lt;2.2&amp;gt;, &amp;lt;3&amp;gt;, &amp;lt;4&amp;gt;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; field !! Position value replacement, if feature specified (only types and prefixes specified) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.None&amp;lt;/code&amp;gt; || &amp;lt;1&amp;gt;, &amp;lt;2.2&amp;gt;, &amp;lt;3&amp;gt;, &amp;lt;4&amp;gt; = Empty&amp;lt;br/&amp;gt;&amp;lt;2.1&amp;gt; = &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || The method may not have any of the features.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassTargetType&amp;lt;/code&amp;gt; || &amp;lt;1&amp;gt; = Target type || The method may be passed a reference to the target type that initially called the hooked method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; || &amp;lt;2.1&amp;gt; = &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;If target has a return type:&amp;lt;br/&amp;gt;&amp;lt;2.2&amp;gt; = &amp;lt;code&amp;gt;out &amp;lt;return type&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;Otherwise:&amp;lt;br/&amp;gt;&amp;lt;2.2&amp;gt; = Empty || The hook method is a redirect and thus may be passed a reference to the return value (if there is such). If the the target method has a return value of type &amp;lt;code&amp;gt;&amp;lt;return type&amp;gt;&amp;lt;/code&amp;gt;, a parameter of the same type is passed as a reference to the hook method.&amp;lt;br/&amp;gt;'''Note:''' If the feature is not specified, &amp;lt;2.1&amp;gt; must be &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt; || &amp;lt;3&amp;gt; = &amp;lt;code&amp;gt;ref &amp;lt;type1&amp;gt;, ref &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass references to the target type's member fields (assuming target method is not static) specified by the &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; creation method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMethodParametersByValue&amp;lt;/code&amp;gt; || &amp;lt;4&amp;gt; = &amp;lt;code&amp;gt;&amp;lt;type1&amp;gt;, &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass its own parameters to the hook. Since they are passed by value, they cannot be altered.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMethodParametersByReference&amp;lt;/code&amp;gt; || &amp;lt;4&amp;gt; = &amp;lt;code&amp;gt;ref &amp;lt;type1&amp;gt;, ref &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass its own parameters to the hook. Since they are passed by reference, they can be altered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Some important things to point out:&lt;br /&gt;
* The hook method '''must''' be public and static! Otherwise it is impossible to hook it anywhere.&lt;br /&gt;
* Some of the above-mentioned features can be left out. However the order of the parameters must be always preserved!&lt;br /&gt;
* If &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; is set, the hook method must return a &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the hook method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the execution of the original target method's instructions is interrupted; the target method simply returns the result value it got from the hook method (if any). In the contrary, if the hook method return &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the original target method will continue its execution after the hook method has completed executing its instructions.&lt;br /&gt;
* Legacy notice: &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; makes ReiPatcherPlus search for a redirect method. However, since both hooking and redirecting have been combined into one single method, there is no point in differentiating between them anymore.&lt;br /&gt;
&lt;br /&gt;
The features may be combined with a logical OR operator (&amp;lt;code&amp;gt;|&amp;lt;/code&amp;gt;). In addition to the features above, the &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; enumeration has the following feature combinations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Feature !! Combination equivalent&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.All_ByValue&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;MethodFeatures.PassTargetType | MethodFeatures.PassReturn | MethodFeatures.PassMemberReferences | MethodFeatures.PassMethodParametersByValue&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.All_ByReference&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;MethodFeatures.PassTargetType | MethodFeatures.PassReturn | MethodFeatures.PassMemberReferences | MethodFeatures.PassMethodParametersByReference&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 // Getting type definition for the class that contains all the hook methods&lt;br /&gt;
 TypeDefinition hookType = HookModule.GetType(&amp;quot;MyHookNamespace.Hook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 MethodDefinition m2 = swallowType.GetMethod(&amp;quot;MakeFly&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
 // Valid hook method prototype: public static void GetNeededSwallowsHook1()&lt;br /&gt;
 MethodHook hookM1 = this.GetHookMethod(m1, &lt;br /&gt;
                                        hookType, &lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook1&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.None);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool GetNeededSwallowsHook2(Swallow self, out float result, int coconuts)&lt;br /&gt;
 MethodHook hookM2 = this.GetHookMethod(m1,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook2&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByValue);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool GetNeededSwallowsHook3(Swallow self, out float result, ref int coconuts)									&lt;br /&gt;
 MethodHook hookM3 = this.GetHookMethod(m1,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook3&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByReference);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool MakeFlyHook(Swallow self, out float result, ref float airSpeedVelocity, int coconuts)									&lt;br /&gt;
 MethodHook hookM4 = this.GetHookMethod(m2,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;MakeFlyHook&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMemberReferences&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByValue,&lt;br /&gt;
                                        swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;));&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition hookMethod = hookType.GetMethod(&amp;quot;MakeFlyHook2&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool MakeFlyHook(Swallow self, out float result, ref float airSpeedVelocity, ref int coconuts)									&lt;br /&gt;
 MethodHook hookM5 = MethodHook.FromMethodDefinition(m2,&lt;br /&gt;
                                                     hookMethod,&lt;br /&gt;
                                                     MethodFeatures.All_ByReference,&lt;br /&gt;
                                                     swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Injecting the methods ===&lt;br /&gt;
Finally, ReiPatcherPlus provides a functionality to patch methods. That can be done with &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
The exact definitions and parameter descriptions are below:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void AttachMethod(MethodHook hook, int codeOffset);&lt;br /&gt;
 void AttachMethod(MethodDefinition target, &lt;br /&gt;
                   MethodDefinition hook, &lt;br /&gt;
                   int codeOffset, &lt;br /&gt;
                   MethodFeatures features,&lt;br /&gt;
                   params FieldDefinition[] memberReferences);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;target&amp;lt;/code&amp;gt; || The method definition of the method which is to be hooked.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodDefinition hook&amp;lt;/code&amp;gt; || Method definition of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; || The criteria by which the hook method should be chosen. Defines the structure of the hook method. '''Default: ''' &amp;lt;code&amp;gt;MethodFeatures.None&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memberReferences&amp;lt;/code&amp;gt; || If one of the criteria is &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt;, specifies the fields that are to be passed to the method.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;MethodHook hook&amp;lt;/code&amp;gt; || An instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; that contains all the appropriate information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;codeOffset&amp;lt;/code&amp;gt; || An index value of an IL instruction in the target method from which to begin injection. If set to negative, will begin counting from the last instruction of the target method, where -1 is being the last instruction.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Elementary, these two methods will automatically inject the needed CIL instructions depending on the chosen hook/target method.&amp;lt;br/&amp;gt;&lt;br /&gt;
The latter method will verify the compatibility between the target and the hook before applying the patch. That method is equivalent to calling &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt; and then &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Most of the time setting code offset to 0 will be sufficient for plug-ins. However, if one wants to place the hook at a certain place, refer to the previous sections on how to decompile the .NET code. Most of the decompilers come with IL decompilers bundled (like ILSpy), which allows to inspect pure IL instructions to find the perfect attachment point.&lt;br /&gt;
&lt;br /&gt;
Note as well that &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt; will always add its own CIL instructions '''before''' the specified code offset! That is done to prevent the developers from inserting method hooks after the &amp;lt;code&amp;gt;ret&amp;lt;/code&amp;gt; instruction that is always present as a last IL instruction in every method. Any code insterted after the said instruction is simply neglected by the machine.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 TypeDefinition hookType = HookModule.GetType(&amp;quot;MyHookNamespace.Hook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method prototype: public static void GetNeededSwallowsHook1()&lt;br /&gt;
 MethodHook hookM1 = this.GetHookMethod(m1, &lt;br /&gt;
                                        hookType, &lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook1&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.None);&lt;br /&gt;
 &lt;br /&gt;
 this.AttachMethod(hookM1, 0);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Debugging functions ===&lt;br /&gt;
ReiPatcherPlus provides simple methods for patcher message logging. All of the logging methods are located in &amp;lt;code&amp;gt;RPPLogger&amp;lt;/code&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
However, to enable logging, one must use the DEV version of the ReiPatcherPlus (slightly larger file size than normal ReiPatcherPlus).&lt;br /&gt;
After that, one can set &amp;lt;code&amp;gt;RPPLogger.VERBOSE_LEVEL&amp;lt;/code&amp;gt; variable to enable logging of certain methods.&lt;br /&gt;
&lt;br /&gt;
Possible variable values are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.None&amp;lt;/code&amp;gt; || Don't output any messages&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.Patcher&amp;lt;/code&amp;gt; || Output patcher-related messages (getting hook methods, attaching methods, etc.).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.Cecil&amp;lt;/code&amp;gt; || Output Mono.Cecil-related extension method messages. Includes parameter equality checking and method searching.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The flags can be combined with a logical OR (&amp;lt;code&amp;gt;|&amp;lt;/code&amp;gt;) operator.&lt;br /&gt;
&lt;br /&gt;
If one whishes to output own logging messages, it is possible through the following methods located in &amp;lt;code&amp;gt;RPPLogger&amp;gt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void Log(string message, VerboseLevel level, bool addPrefix);&lt;br /&gt;
 void LogLine(string message, VerboseLevel level, bool addPrefix);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the parameters:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt; || Message to output.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; || The level to output the message to. Used to filter the output based on selected levels.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;addPrefix&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will append a prefix specified on &amp;lt;code&amp;gt;RPPLogger.PREFIX&amp;lt;/code&amp;gt; before the specified &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The difference between the methods is that the latter will add a line break to the message, while the former one will not.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Set verbose level to patcher only&lt;br /&gt;
 RPPLogger.VERBOSE_LEVEL = RPPLogger.VerboseLevel.Patcher;&lt;br /&gt;
 &lt;br /&gt;
 // Will be shown in ReiPatcher console&lt;br /&gt;
 RPPLogger.LogLine(&amp;quot;Hello, log!&amp;quot;, RPPLogger.VerboseLevel.Patcher);&lt;br /&gt;
 &lt;br /&gt;
 // Won't be seen in ReiPatcher&lt;br /&gt;
 RPPLogger.LogLine(&amp;quot;I am hidden!&amp;quot;, RPPLogger.VerboseLevel.Cecil);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Legacy and other obsolete methods ===&lt;br /&gt;
These methods are marked as obsolete and must not be used. Instead, use the newer functionality of ReiPatcherPlus.&lt;br /&gt;
&lt;br /&gt;
==== Method hooking ====&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Method redirecting ====&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18211</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18211"/>
				<updated>2015-08-12T16:20:26Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Please note that owing to ever-so-evolving patching tools some parts of the tutorial may be outdated. The developers of said tools try their best to bring more features while trying to preserve the original programming routines. However, changes happen and the editors of this wiki attempt to update the documentation as fast as possible.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be almost impossible to manipulate, which is due to the code being mostly unmanaged (notice that the managed code is still compiled into CIL, albeit with &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt; tag.).&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
'''NOTE:''' Since ReiPatcherPlus 2.0, the library has undergone some major changes in structure. Therefore, note that some of parts of this page concerning ReiPatcherPlus might be outdated.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2(x84/x64)_Data\Managed&amp;lt;/code&amp;gt; folder at the very least.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Inspecting original code with a decompiler ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&amp;lt;/br&amp;gt;&lt;br /&gt;
'''Note:''' You can copy &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; as well, but remember that if you intend on using UnityInjector along with ReiPatcher, consider referencing the assembly directly from game directory instead. That way, after ReiPatcher had applied the patches, the IDE will automatically pick up updated method and visibility definitions.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming conventions ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, as of this moment, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. The hook DLL acts more often than not as a bridge between the game's own internal API and our plug-in code.&lt;br /&gt;
&lt;br /&gt;
If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good practice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies. &lt;br /&gt;
The patcher DLL is used by ReiPatcher to allow the plug-in developer to inject custom calls to the hook methods, change member field access and adding own code.&lt;br /&gt;
&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
Every assembly that one wishes to be patched must be requested. Otherwise it might not be included into the patching cycle.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times and on the right assemblies.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if our patch has already been applied to the specified assembly. That way we can avoid injecting the same code twice.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
The contents of the method depend on the situation. However, in almost all cases patching requires using various methods provided by Mono.Cecil to alter the contents of classes and methods.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps if we are to use pure Cecil and CIL:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, method search and injecting can be done easier with ReiPatcherPlus.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here are the main steps in using ReiPatcherPlus:&lt;br /&gt;
&lt;br /&gt;
'''1. Acquiring the type definitions'''&amp;lt;br/&amp;gt;&lt;br /&gt;
This is done simply with Mono.Cecil's &amp;lt;code&amp;gt;ModuleDefinition.GetType(string name)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
 TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''2. Getting the target method and the appropriate hook'''&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides an extension to Mono.Cecil: &amp;lt;code&amp;gt;TypeDefinition.GetMethod(string name)&amp;lt;/code&amp;gt; which searches for the first method with the given name.&amp;lt;br/&amp;gt;&lt;br /&gt;
Furthermore, to get a suiting hook method, we can use &amp;lt;code&amp;gt;GetHookMethod(MethodDefinition target, TypeDefinition hookType, string hookName, MethodFeatures features)&amp;lt;/code&amp;gt; which finds a suitable hook method that matches both the target method and the given criteria.&lt;br /&gt;
Since our hook method has only a parameter of the target type, only using the feature &amp;lt;code&amp;gt;MethodFeatures.PassTargetType&amp;lt;/code&amp;gt; will suffice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
 MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more detailed discussion on method features and &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, refer to the later sections.&lt;br /&gt;
&lt;br /&gt;
'''3. Injecting the code'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Having created an instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt;, we can now simply use ReiPatcherPlus's &amp;lt;code&amp;gt;AttachMethod(MethodHook hook, int codeOffset)&amp;lt;/code&amp;gt;. Since the hook method was searched with &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, one can be sure that the hook method is in fact injectable into the target method.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;int codeOffset&amp;lt;/code&amp;gt; specifies the index of the IL code to start the injection from. Since we want to add the hook at the beginning of the &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;, we simply pass 0:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 this.AttachMethod(hookMethod, 0);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putting it all together we get a fancy patch method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Get type definitions for the UIButton and the hook class&lt;br /&gt;
     TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
     TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
     // Get the method definition for OnClick and OnClickHook&lt;br /&gt;
     // GetHookMethod assures that the created MethodHook instance contains a valid hook for OnClick&lt;br /&gt;
     MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
     MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
     &lt;br /&gt;
     // Passing 0 will inject the hook method at the beginning of OnClick method&lt;br /&gt;
     this.AttachMethod(hookMethod, 0);&lt;br /&gt;
     &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Box1 start}}&lt;br /&gt;
'''NOTE:''' The alternative below is listed only for legacy reasons. ReiPatcherPlus 2.0+ marks &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; as obsolete. Consider using the above-mentioned code.&lt;br /&gt;
{{Boxes end}}&lt;br /&gt;
&lt;br /&gt;
Alternatively, ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
             TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
             &lt;br /&gt;
             MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
             MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
             &lt;br /&gt;
             this.AttachMethod(hookMethod, 0);&lt;br /&gt;
             &lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL (using UnityInjector) ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehaviour&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that the name of plug-in's INI configuration file will be the same as plug-in class name. In our case, calling &amp;lt;code&amp;gt;SaveConfig()&amp;lt;/code&amp;gt; will create a configuration file named &amp;lt;code&amp;gt;HelloWorldPlugin.ini&amp;lt;/code&amp;gt; which will be saved to &amp;lt;code&amp;gt;&amp;lt;Game's main directory&amp;gt;\UnityInjector\Config&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command below&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
In the examples we shall use the following class that contains potential methods to hook:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         protected enum SwallowType&lt;br /&gt;
         {&lt;br /&gt;
             European,&lt;br /&gt;
             African&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
         private float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public float GetNeededSwallows(float distance);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         public static T FirstSwallow&amp;lt;T&amp;gt;(List&amp;lt;T&amp;gt; swallows);&lt;br /&gt;
         public static T FirstSwallow&amp;lt;T&amp;gt;(List&amp;lt;T&amp;gt; swallows, T addition);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting methods and fields ===&lt;br /&gt;
ReiPatcherPlus adds two new extension methods to Mono.Cecil that allow to locate method definitions in their respected types.&lt;br /&gt;
Those methods are added as extensions to &amp;lt;code&amp;gt;Mono.Cecil.TypeDefinition&amp;lt;/code&amp;gt; type.&amp;lt;br/&amp;gt;&lt;br /&gt;
Those two methods are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodDefinition GetMethod(string methodName);&lt;br /&gt;
 MethodDefinition GetMethod(string methodName, params TypeReference[] paramTypes);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;methodName&amp;lt;/code&amp;gt; || Name of the method to search for.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;paramTypes&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;TypeReference&amp;lt;/code&amp;gt; representation of method parameters. Used to search for the exact overload of a method.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Furthermore, one can easily acquire member fields (delegates, variables) of the type. That is done with the method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 FieldDefinition GetField(string memberName);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where &amp;lt;code&amp;gt;memberName&amp;lt;/code&amp;gt; is name of the member to search for.&lt;br /&gt;
&lt;br /&gt;
In both cases, the methods will return &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;, if the fitting method/field has not been found. Therefore, it is up to the developer to make sure the provided parameters point to a valid method or field. &lt;br /&gt;
In some cases, the programmer may need to perform null checking.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Will return GetNeededSwallows(int)&lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Will return GetNeededSwallows(float)&lt;br /&gt;
 MethodDefinition m2 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;, Parameter.FromType&amp;lt;float&amp;gt;());&lt;br /&gt;
 &lt;br /&gt;
 FieldDefinition f1 = swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Handling parameters ===&lt;br /&gt;
To make turning &amp;lt;code&amp;gt;System.Type&amp;lt;/code&amp;gt; and normal type declarations into dummy &amp;lt;code&amp;gt;TypeReference&amp;lt;/code&amp;gt;s to use with ReiPatcherPlus, &amp;lt;code&amp;gt;Parameter&amp;lt;/code&amp;gt; class was created.&lt;br /&gt;
The class houses a panoply of useful methods to create &amp;quot;dummy type references&amp;quot; (they are not actual references to the real types -- instead, they are containers for type information used method search methods).&amp;lt;br/&amp;gt;&lt;br /&gt;
Such methods are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeReference FromType(Type type, params string[] genericTypeNames);&lt;br /&gt;
 TypeReference FromType&amp;lt;T&amp;gt;();&lt;br /&gt;
 TypeReference FromTypeRef(Type type, params string[] genericTypeNames);&lt;br /&gt;
 &lt;br /&gt;
 TypeReference CreateGeneric(string name);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the first four methods, the parameter descriptions are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;System.Type&amp;lt;/code&amp;gt; representation of the given type. Can be acquired with &amp;lt;code&amp;gt;typeof(TypeName)&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;genericTypeNames&amp;lt;/code&amp;gt; || Names of the generic types. Used only, if the provided &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; has undefined generic parameters.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; || Type name of the type to be converted. Calling &amp;lt;code&amp;gt;FromType&amp;lt;T&amp;gt;()&amp;lt;/code&amp;gt; has the same effect as &amp;lt;code&amp;gt;FromType(typeof(T))&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
As for &amp;lt;code&amp;gt;CreateGeneric&amp;lt;/code&amp;gt;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; || Name of the generic type to create.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note that in order for &amp;lt;code&amp;gt;GetMethod&amp;lt;/code&amp;gt; to succeed with generic types, the names of those must stay the same. If the original method had a generic type &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;, one must make the type with &amp;lt;code&amp;gt;Parameter.MakeGeneric(&amp;quot;T&amp;quot;)&amp;lt;/code&amp;gt; in order for the method to be found.&lt;br /&gt;
The same principle must hold when matching target method parameters with the hook method parameters.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // t1 and t2 are technically the same &lt;br /&gt;
 TypeReference t1 = Parameter.FromType(typeof(int));&lt;br /&gt;
 TypeReference t2 = Parameter.FromType&amp;lt;int&amp;gt;();&lt;br /&gt;
 &lt;br /&gt;
 // Creates a type of List&amp;lt;T&amp;gt;&lt;br /&gt;
 TypeReference t3 = Parameter.FromType(typeof(List&amp;lt;&amp;gt;), &amp;quot;T&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Creates a reference type System.Boolean&amp;amp;&lt;br /&gt;
 TypeReference t4 = Parameter.FromTypeRef(typeof(bool));&lt;br /&gt;
 &lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m3 = swallowType.GetMethod(&amp;quot;MakeFly&amp;quot;, Parameter.FromType&amp;lt;bool&amp;gt;(), Parameter.FromType&amp;lt;float&amp;gt;());&lt;br /&gt;
 MethodDefinition m4 = swallowType.GetMethod(&amp;quot;FirstSwallow&amp;quot;, Parameter.FromType(typeof(List&amp;lt;&amp;gt;), &amp;quot;T&amp;quot;), Parameter.CreateGeneric(&amp;quot;T&amp;quot;));&lt;br /&gt;
 &lt;br /&gt;
 // WILL NOT WORK: The provided generic types differ from the original definition&lt;br /&gt;
 MethodDefinition m5 = swallowType.GetMethod(&amp;quot;FirstSwallow&amp;quot;, Parameter.FromType(typeof(List&amp;lt;&amp;gt;),&amp;quot;A&amp;quot;), Parameter.CreateGeneric(&amp;quot;G&amp;quot;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The MethodHook type and getting hooks ===&lt;br /&gt;
To provide an easy patching experience, ReiPatcherPlus includes &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; container that exposes the following get-only properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Hook&amp;lt;/code&amp;gt; || Method definition of the hook method. Will be hooked to the target.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Features&amp;lt;/code&amp;gt; || Additional criteria by which the hook method was chosen. Refer to the next subsection for more information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Target&amp;lt;/code&amp;gt; || Method definition of the method to hook (target method).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The creation of the &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; instance is controlled internally from ReiPatcherPlus. That way the library guarantees that the specified hook-target pair is valid and injectable.&lt;br /&gt;
&lt;br /&gt;
Currently there are two ways of getting the instance: by using &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; extension &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt; or by calling &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The exact definitions are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodHook GetHookMethod(MethodDefinition target, &lt;br /&gt;
                          TypeDefinition hookType, &lt;br /&gt;
                          string hookName, &lt;br /&gt;
                          MethodFeatures features, &lt;br /&gt;
                          params FieldDefinition[] memberReferences);&lt;br /&gt;
 &lt;br /&gt;
 MethodHook MethodHook.FromMethodDefinition(MethodDefinition target, &lt;br /&gt;
                                            MethodDefinition hook, &lt;br /&gt;
                                            MethodFeatures features, &lt;br /&gt;
                                            params FieldDefinition[] memberReferences);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The parameter description is the following:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;target&amp;lt;/code&amp;gt; || The method definition of the method which is to be hooked.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || The type (class/struct) that possesses the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; || The criteria by which the hook method should be chosen. Defines the structure of the hook method. Refer to the next subsection for more information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memberReferences&amp;lt;/code&amp;gt; || If one of the criteria is &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt;, specifies the fields that are to be passed to the method.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;hook&amp;lt;/code&amp;gt; || Method definition of the hook method.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
While using the methods, note the following:&lt;br /&gt;
* When using &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, the final &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; might be different from the ones specified. That is simply because the method adapts to its passed parameters to find the best hook method.&lt;br /&gt;
However, the method attempts to find the best hook without throwing any exceptions (for the exception of &amp;lt;code&amp;gt;ArgumentException&amp;lt;/code&amp;gt; if the provided member fields do not belong to the target type).&lt;br /&gt;
* &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt; strictly checks whether the provided target and hook are injectable. If a discrepancy is found, the method will throw an exception containing the reason the method failed.&lt;br /&gt;
* Prefer using &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, as it mostly exception-free and will return either a working instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Method Features ====&lt;br /&gt;
To allow the developer to freely choose which kind of hook to use, what parameters to pass and what to return, ReiPatcherPlus allows to specify certain criteria that define the layot of the hook method.&lt;br /&gt;
Albeit allowing different set of parameters to be passed, the hook method must have its parameters in a certain order for ReiPatcherPlus to work with them.&lt;br /&gt;
&lt;br /&gt;
Below is the hook method template with numbered positions and a table of what types are allowed in place of those positions and which &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; fields to use to enable those positions:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static &amp;lt;2.1&amp;gt; MyHookMethod(&amp;lt;1&amp;gt;, &amp;lt;2.2&amp;gt;, &amp;lt;3&amp;gt;, &amp;lt;4&amp;gt;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; field !! Position value replacement, if feature specified (only types and prefixes specified) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.None&amp;lt;/code&amp;gt; || &amp;lt;1&amp;gt;, &amp;lt;2.2&amp;gt;, &amp;lt;3&amp;gt;, &amp;lt;4&amp;gt; = Empty&amp;lt;br/&amp;gt;&amp;lt;2.1&amp;gt; = &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || The method may not have any of the features.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassTargetType&amp;lt;/code&amp;gt; || &amp;lt;1&amp;gt; = Target type || The method may be passed a reference to the target type that initially called the hooked method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; || &amp;lt;2.1&amp;gt; = &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;If target has a return type:&amp;lt;br/&amp;gt;&amp;lt;2.2&amp;gt; = &amp;lt;code&amp;gt;out &amp;lt;return type&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;Otherwise:&amp;lt;br/&amp;gt;&amp;lt;2.2&amp;gt; = Empty || The hook method is a redirect and thus may be passed a reference to the return value (if there is such). If the the target method has a return value of type &amp;lt;code&amp;gt;&amp;lt;return type&amp;gt;&amp;lt;/code&amp;gt;, a parameter of the same type is passed as a reference to the hook method.&amp;lt;br/&amp;gt;'''Note:''' If the feature is not specified, &amp;lt;2.1&amp;gt; must be &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt; || &amp;lt;3&amp;gt; = &amp;lt;code&amp;gt;ref &amp;lt;type1&amp;gt;, ref &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass references to the target type's member fields (assuming target method is not static) specified by the &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; creation method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMethodParametersByValue&amp;lt;/code&amp;gt; || &amp;lt;4&amp;gt; = &amp;lt;code&amp;gt;&amp;lt;type1&amp;gt;, &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass its own parameters to the hook. Since they are passed by value, they cannot be altered.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMethodParametersByReference&amp;lt;/code&amp;gt; || &amp;lt;4&amp;gt; = &amp;lt;code&amp;gt;ref &amp;lt;type1&amp;gt;, ref &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass its own parameters to the hook. Since they are passed by reference, they can be altered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Some important things to point out:&lt;br /&gt;
* The hook method '''must''' be public and static! Otherwise it is impossible to hook it anywhere.&lt;br /&gt;
* Some of the above-mentioned features can be left out. However the order of the parameters must be always preserved!&lt;br /&gt;
* If &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; is set, the hook method must return a &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the hook method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the execution of the original target method's instructions is interrupted; the target method simply returns the result value it got from the hook method (if any). In the contrary, if the hook method return &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the original target method will continue its execution after the hook method has completed executing its instructions.&lt;br /&gt;
* Legacy notice: &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; makes ReiPatcherPlus search for a redirect method. However, since both hooking and redirecting have been combined into one single method, there is no point in differentiating between them anymore.&lt;br /&gt;
&lt;br /&gt;
The features may be combined with a logical OR operator (&amp;lt;code&amp;gt;|&amp;lt;/code&amp;gt;). In addition to the features above, the &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; enumeration has the following feature combinations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Feature !! Combination equivalent&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.All_ByValue&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;MethodFeatures.PassTargetType | MethodFeatures.PassReturn | MethodFeatures.PassMemberReferences | MethodFeatures.PassMethodParametersByValue&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.All_ByReference&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;MethodFeatures.PassTargetType | MethodFeatures.PassReturn | MethodFeatures.PassMemberReferences | MethodFeatures.PassMethodParametersByReference&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 // Getting type definition for the class that contains all the hook methods&lt;br /&gt;
 TypeDefinition hookType = HookModule.GetType(&amp;quot;MyHookNamespace.Hook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 MethodDefinition m2 = swallowType.GetMethod(&amp;quot;MakeFly&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
 // Valid hook method prototype: public static void GetNeededSwallowsHook1()&lt;br /&gt;
 MethodHook hookM1 = this.GetHookMethod(m1, &lt;br /&gt;
                                        hookType, &lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook1&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.None);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool GetNeededSwallowsHook2(Swallow self, out float result, int coconuts)&lt;br /&gt;
 MethodHook hookM2 = this.GetHookMethod(m1,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook2&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByValue);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool GetNeededSwallowsHook3(Swallow self, out float result, ref int coconuts)									&lt;br /&gt;
 MethodHook hookM3 = this.GetHookMethod(m1,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook3&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByReference);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool MakeFlyHook(Swallow self, out float result, ref float airSpeedVelocity, int coconuts)									&lt;br /&gt;
 MethodHook hookM4 = this.GetHookMethod(m2,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;MakeFlyHook&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMemberReferences&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByValue,&lt;br /&gt;
                                        swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;));&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition hookMethod = hookType.GetMethod(&amp;quot;MakeFlyHook2&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool MakeFlyHook(Swallow self, out float result, ref float airSpeedVelocity, ref int coconuts)									&lt;br /&gt;
 MethodHook hookM5 = MethodHook.FromMethodDefinition(m2,&lt;br /&gt;
                                                     hookMethod,&lt;br /&gt;
                                                     MethodFeatures.All_ByReference,&lt;br /&gt;
                                                     swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Injecting the methods ===&lt;br /&gt;
Finally, ReiPatcherPlus provides a functionality to patch methods. That can be done with &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
The exact definitions and parameter descriptions are below:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void AttachMethod(MethodHook hook, int codeOffset);&lt;br /&gt;
 void AttachMethod(MethodDefinition target, &lt;br /&gt;
                   MethodDefinition hook, &lt;br /&gt;
                   int codeOffset, &lt;br /&gt;
                   MethodFeatures features,&lt;br /&gt;
                   params FieldDefinition[] memberReferences);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;target&amp;lt;/code&amp;gt; || The method definition of the method which is to be hooked.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodDefinition hook&amp;lt;/code&amp;gt; || Method definition of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; || The criteria by which the hook method should be chosen. Defines the structure of the hook method. '''Default: ''' &amp;lt;code&amp;gt;MethodFeatures.None&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memberReferences&amp;lt;/code&amp;gt; || If one of the criteria is &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt;, specifies the fields that are to be passed to the method.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;MethodHook hook&amp;lt;/code&amp;gt; || An instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; that contains all the appropriate information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;codeOffset&amp;lt;/code&amp;gt; || An index value of an IL instruction in the target method from which to begin injection. If set to negative, will begin counting from the last instruction of the target method, where -1 is being the last instruction.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Elementary, these two methods will automatically inject the needed CIL instructions depending on the chosen hook/target method.&amp;lt;br/&amp;gt;&lt;br /&gt;
The latter method will verify the compatibility between the target and the hook before applying the patch. That method is equivalent to calling &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt; and then &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Most of the time setting code offset to 0 will be sufficient for plug-ins. However, if one wants to place the hook at a certain place, refer to the previous sections on how to decompile the .NET code. Most of the decompilers come with IL decompilers bundled (like ILSpy), which allows to inspect pure IL instructions to find the perfect attachment point.&lt;br /&gt;
Note as well that &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt; will always add its own CIL instructions '''before''' the specified code offset! That is done to prevent the developers to insert method hooks after the &amp;lt;code&amp;gt;ret&amp;lt;/code&amp;gt; instruction that is always present as a last IL instruction in every method. Any code insterted after the said instruction is simply neglected by the machine.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 TypeDefinition hookType = HookModule.GetType(&amp;quot;MyHookNamespace.Hook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method prototype: public static void GetNeededSwallowsHook1()&lt;br /&gt;
 MethodHook hookM1 = this.GetHookMethod(m1, &lt;br /&gt;
                                        hookType, &lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook1&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.None);&lt;br /&gt;
 &lt;br /&gt;
 this.AttachMethod(hookM1, 0);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Debugging functions ===&lt;br /&gt;
ReiPatcherPlus provides simple methods for patcher message logging. All of the logging methods are located in &amp;lt;code&amp;gt;RPPLogger&amp;lt;/code&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
However, to enable logging, one must use the DEV version of the ReiPatcherPlus (slightly larger file size than normal ReiPatcherPlus).&lt;br /&gt;
After that, one can set &amp;lt;code&amp;gt;RPPLogger.VERBOSE_LEVEL&amp;lt;/code&amp;gt; variable to enable logging of certain methods.&lt;br /&gt;
&lt;br /&gt;
Possible variable values are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.None&amp;lt;/code&amp;gt; || Don't output any messages&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.Patcher&amp;lt;/code&amp;gt; || Output patcher-related messages (getting hook methods, attaching methods, etc.).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.Cecil&amp;lt;/code&amp;gt; || Output Mono.Cecil-related extension method messages. Includes parameter equality checking and method searching.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The flags can be combined with a logical OR (&amp;lt;code&amp;gt;|&amp;lt;/code&amp;gt;) operator.&lt;br /&gt;
&lt;br /&gt;
If one whishes to output own logging messages, it is possible through the following methods located in &amp;lt;code&amp;gt;RPPLogger&amp;gt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void Log(string message, VerboseLevel level, bool addPrefix);&lt;br /&gt;
 void LogLine(string message, VerboseLevel level, bool addPrefix);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the parameters:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt; || Message to output.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; || The level to output the message to. Used to filter the output based on selected levels.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;addPrefix&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will append a prefix specified on &amp;lt;code&amp;gt;RPPLogger.PREFIX&amp;lt;/code&amp;gt; before the specified &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The difference between the methods is that the latter will add a line break to the message, while the former one will not.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Set verbose level to patcher only&lt;br /&gt;
 RPPLogger.VERBOSE_LEVEL = RPPLogger.VerboseLevel.Patcher;&lt;br /&gt;
 &lt;br /&gt;
 // Will be shown in ReiPatcher console&lt;br /&gt;
 RPPLogger.LogLine(&amp;quot;Hello, log!&amp;quot;, RPPLogger.VerboseLevel.Patcher);&lt;br /&gt;
 &lt;br /&gt;
 // Won't be seen in ReiPatcher&lt;br /&gt;
 RPPLogger.LogLine(&amp;quot;I am hidden!&amp;quot;, RPPLogger.VerboseLevel.Cecil);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Legacy and other obsolete methods ===&lt;br /&gt;
These methods are marked as obsolete and must not be used. Instead, use the newer functionality of ReiPatcherPlus.&lt;br /&gt;
&lt;br /&gt;
==== Method hooking ====&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Method redirecting ====&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18210</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18210"/>
				<updated>2015-08-12T15:59:40Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: Fixed some typos, updated documentation for ReiPatcherPlus&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Please note that owing to ever-so-evolving patching tools some parts of the tutorial may be outdated. The developers of said tools try their best to bring more features while trying to preserve the original programming routines. However, changes happen and the editors of this wiki attempt to update the documentation as fast as possible.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be almost impossible to manipulate, which is due to the code being mostly unmanaged (notice that the managed code is still compiled into CIL, albeit with &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt; tag.).&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
'''NOTE:''' Since ReiPatcherPlus 2.0, the library has undergone some major changes in structure. Therefore, note that some of parts of this page concerning ReiPatcherPlus might be outdated.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2(x84/x64)_Data\Managed&amp;lt;/code&amp;gt; folder at the very least.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Inspecting original code with a decompiler ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&amp;lt;/br&amp;gt;&lt;br /&gt;
'''Note:''' You can copy &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; as well, but remember that if you intend on using UnityInjector along with ReiPatcher, consider referencing the assembly directly from game directory instead. That way, after ReiPatcher had applied the patches, the IDE will automatically pick up updated method and visibility definitions.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming conventions ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, as of this moment, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. The hook DLL acts more often than not as a bridge between the game's own internal API and our plug-in code.&lt;br /&gt;
&lt;br /&gt;
If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good practice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies. &lt;br /&gt;
The patcher DLL is used by ReiPatcher to allow the plug-in developer to inject custom calls to the hook methods, change member field access and adding own code.&lt;br /&gt;
&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
Every assembly that one wishes to be patched must be requested. Otherwise it might not be included into the patching cycle.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times and on the right assemblies.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if our patch has already been applied to the specified assembly. That way we can avoid injecting the same code twice.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
The contents of the method depend on the situation. However, in almost all cases patching requires using various methods provided by Mono.Cecil to alter the contents of classes and methods.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps if we are to use pure Cecil and CIL:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, method search and injecting can be done easier with ReiPatcherPlus.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here are the main steps in using ReiPatcherPlus:&lt;br /&gt;
&lt;br /&gt;
'''1. Acquiring the type definitions'''&amp;lt;br/&amp;gt;&lt;br /&gt;
This is done simply with Mono.Cecil's &amp;lt;code&amp;gt;ModuleDefinition.GetType(string name)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
 TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''2. Getting the target method and the appropriate hook'''&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides an extension to Mono.Cecil: &amp;lt;code&amp;gt;TypeDefinition.GetMethod(string name)&amp;lt;/code&amp;gt; which searches for the first method with the given name.&amp;lt;br/&amp;gt;&lt;br /&gt;
Furthermore, to get a suiting hook method, we can use &amp;lt;code&amp;gt;GetHookMethod(MethodDefinition target, TypeDefinition hookType, string hookName, MethodFeatures features)&amp;lt;/code&amp;gt; which finds a suitable hook method that matches both the target method and the given criteria.&lt;br /&gt;
Since our hook method has only a parameter of the target type, only using the feature &amp;lt;code&amp;gt;MethodFeatures.PassTargetType&amp;lt;/code&amp;gt; will suffice:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
 MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more detailed discussion on method features and &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, refer to the later sections.&lt;br /&gt;
&lt;br /&gt;
'''3. Injecting the code'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Having created an instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt;, we can now simply use ReiPatcherPlus's &amp;lt;code&amp;gt;AttachMethod(MethodHook hook, int codeOffset)&amp;lt;/code&amp;gt;. Since the hook method was searched with &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, one can be sure that the hook method is in fact injectable into the target method.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;int codeOffset&amp;lt;/code&amp;gt; specifies the index of the IL code to start the injection from. Since we want to add the hook at the beginning of the &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;, we simply pass 0:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 this.AttachMethod(hookMethod, 0);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Putting it all together we get a fancy patch method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Get type definitions for the UIButton and the hook class&lt;br /&gt;
     TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
     TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
     // Get the method definition for OnClick and OnClickHook&lt;br /&gt;
     // GetHookMethod assures that the created MethodHook instance contains a valid hook for OnClick&lt;br /&gt;
     MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
     MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
     &lt;br /&gt;
     // Passing 0 will inject the hook method at the beginning of OnClick method&lt;br /&gt;
     this.AttachMethod(hookMethod, 0);&lt;br /&gt;
     &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Box1 start}}&lt;br /&gt;
'''NOTE:''' The alternative below is listed only for legacy reasons. ReiPatcherPlus 2.0+ marks &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; as obsolete. Consider using the above-mentioned code.&lt;br /&gt;
{{Boxes end}}&lt;br /&gt;
&lt;br /&gt;
Alternatively, ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             TypeDefinition uiButton = args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;);&lt;br /&gt;
             TypeDefinition hooks = hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;);&lt;br /&gt;
             &lt;br /&gt;
             MethodDefinition onClick = uiButton.GetMethod(&amp;quot;OnClick&amp;quot;);&lt;br /&gt;
             MethodHook hookMethod = this.GetHookMethod(onClick, hooks, &amp;quot;OnClickHook&amp;quot;, MethodFeatures.PassTargetType);&lt;br /&gt;
             &lt;br /&gt;
             this.AttachMethod(hookMethod, 0);&lt;br /&gt;
             &lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL (using UnityInjector) ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehaviour&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that the name of plug-in's INI configuration file will be the same as plug-in class name. In our case, calling &amp;lt;code&amp;gt;SaveConfig()&amp;lt;/code&amp;gt; will create a configuration file named &amp;lt;code&amp;gt;HelloWorldPlugin.ini&amp;lt;/code&amp;gt; which will be saved to &amp;lt;code&amp;gt;&amp;lt;Game's main directory&amp;gt;\UnityInjector\Config&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command below&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
In the examples we shall use the following class that contains potential methods to hook:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         protected enum SwallowType&lt;br /&gt;
         {&lt;br /&gt;
             European,&lt;br /&gt;
             African&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
         private float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public float GetNeededSwallows(float distance);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         public static T FirstSwallow&amp;lt;T&amp;gt;(List&amp;lt;T&amp;gt; swallows);&lt;br /&gt;
         public static T FirstSwallow&amp;lt;T&amp;gt;(List&amp;lt;T&amp;gt; swallows, T addition);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting methods and fields ===&lt;br /&gt;
ReiPatcherPlus adds two new extension methods to Mono.Cecil that allow to locate method definitions in their respected types.&lt;br /&gt;
Those methods are added as extensions to &amp;lt;code&amp;gt;Mono.Cecil.TypeDefinition&amp;lt;/code&amp;gt; type.&amp;lt;br/&amp;gt;&lt;br /&gt;
Those two methods are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodDefinition GetMethod(string methodName);&lt;br /&gt;
 MethodDefinition GetMethod(string methodName, params TypeReference[] paramTypes);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;methodName&amp;lt;/code&amp;gt; || Name of the method to search for.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;paramTypes&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;TypeReference&amp;lt;/code&amp;gt; representation of method parameters. Used to search for the exact overload of a method.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Furthermore, one can easily acquire member fields (delegates, variables) of the type. That is done with the method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 FieldDefinition GetField(string memberName);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
where &amp;lt;code&amp;gt;memberName&amp;lt;/code&amp;gt; is name of the member to search for.&lt;br /&gt;
&lt;br /&gt;
In both cases, the methods will return &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;, if the fitting method/field has not been found. Therefore, it is up to the developer to make sure the provided parameters point to a valid method or field. &lt;br /&gt;
In some cases, the programmer may need to perform null checking.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Will return GetNeededSwallows(int)&lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Will return GetNeededSwallows(float)&lt;br /&gt;
 MethodDefinition m2 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;, Parameter.FromType&amp;lt;float&amp;gt;());&lt;br /&gt;
 &lt;br /&gt;
 FieldDefinition f1 = swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Handling parameters ===&lt;br /&gt;
To make turning &amp;lt;code&amp;gt;System.Type&amp;lt;/code&amp;gt; and normal type declarations into dummy &amp;lt;code&amp;gt;TypeReference&amp;lt;/code&amp;gt;s to use with ReiPatcherPlus, &amp;lt;code&amp;gt;Parameter&amp;lt;/code&amp;gt; class was created.&lt;br /&gt;
The class houses a panoply of useful methods to create &amp;quot;dummy type references&amp;quot; (they are not actual references to the real types -- instead, they are containers for type information used method search methods).&amp;lt;br/&amp;gt;&lt;br /&gt;
Such methods are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeReference FromType(Type type, params string[] genericTypeNames);&lt;br /&gt;
 TypeReference FromType&amp;lt;T&amp;gt;();&lt;br /&gt;
 TypeReference FromTypeRef(Type type, params string[] genericTypeNames);&lt;br /&gt;
 &lt;br /&gt;
 TypeReference CreateGeneric(string name);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the first four methods, the parameter descriptions are as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;System.Type&amp;lt;/code&amp;gt; representation of the given type. Can be acquired with &amp;lt;code&amp;gt;typeof(TypeName)&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;genericTypeNames&amp;lt;/code&amp;gt; || Names of the generic types. Used only, if the provided &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; has undefined generic parameters.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;lt;T&amp;gt;&amp;lt;/code&amp;gt; || Type name of the type to be converted. Calling &amp;lt;code&amp;gt;FromType&amp;lt;T&amp;gt;()&amp;lt;/code&amp;gt; has the same effect as &amp;lt;code&amp;gt;FromType(typeof(T))&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
As for &amp;lt;code&amp;gt;CreateGeneric&amp;lt;/code&amp;gt;:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; || Name of the generic type to create.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note that in order for &amp;lt;code&amp;gt;GetMethod&amp;lt;/code&amp;gt; to succeed with generic types, the names of those must stay the same. If the original method had a generic type &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt;, one must make the type with &amp;lt;code&amp;gt;Parameter.MakeGeneric(&amp;quot;T&amp;quot;)&amp;lt;/code&amp;gt; in order for the method to be found.&lt;br /&gt;
The same principle must hold when matching target method parameters with the hook method parameters.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // t1 and t2 are technically the same &lt;br /&gt;
 TypeReference t1 = Parameter.FromType(typeof(int));&lt;br /&gt;
 TypeReference t2 = Parameter.FromType&amp;lt;int&amp;gt;();&lt;br /&gt;
 &lt;br /&gt;
 // Creates a type of List&amp;lt;T&amp;gt;&lt;br /&gt;
 TypeReference t3 = Parameter.FromType(typeof(List&amp;lt;&amp;gt;), &amp;quot;T&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Creates a reference type System.Boolean&amp;amp;&lt;br /&gt;
 TypeReference t4 = Parameter.FromTypeRef(typeof(bool));&lt;br /&gt;
 &lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m3 = swallowType.GetMethod(&amp;quot;MakeFly&amp;quot;, Parameter.FromType&amp;lt;bool&amp;gt;(), Parameter.FromType&amp;lt;float&amp;gt;());&lt;br /&gt;
 MethodDefinition m4 = swallowType.GetMethod(&amp;quot;FirstSwallow&amp;quot;, Parameter.FromType(typeof(List&amp;lt;&amp;gt;), &amp;quot;T&amp;quot;), Parameter.CreateGeneric(&amp;quot;T&amp;quot;));&lt;br /&gt;
 &lt;br /&gt;
 // WILL NOT WORK: The provided generic types differ from the original definition&lt;br /&gt;
 MethodDefinition m5 = swallowType.GetMethod(&amp;quot;FirstSwallow&amp;quot;, Parameter.FromType(typeof(List&amp;lt;&amp;gt;),&amp;quot;A&amp;quot;), Parameter.CreateGeneric(&amp;quot;G&amp;quot;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The MethodHook type and getting hooks ===&lt;br /&gt;
To provide an easy patching experience, ReiPatcherPlus includes &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; container that exposes the following get-only properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Hook&amp;lt;/code&amp;gt; || Method definition of the hook method. Will be hooked to the target.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Features&amp;lt;/code&amp;gt; || Additional criteria by which the hook method was chosen. Refer to the next subsection for more information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Target&amp;lt;/code&amp;gt; || Method definition of the method to hook (target method).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The creation of the &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; instance is controlled internally from ReiPatcherPlus. That way the library guarantees that the specified hook-target pair is valid and injectable.&lt;br /&gt;
&lt;br /&gt;
Currently there are two ways of getting the instance: by using &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; extension &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt; or by calling &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The exact definitions are:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 MethodHook GetHookMethod(MethodDefinition target, &lt;br /&gt;
                          TypeDefinition hookType, &lt;br /&gt;
                          string hookName, &lt;br /&gt;
                          MethodFeatures features, &lt;br /&gt;
                          params FieldDefinition[] memberReferences);&lt;br /&gt;
 &lt;br /&gt;
 MethodHook MethodHook.FromMethodDefinition(MethodDefinition target, &lt;br /&gt;
                                            MethodDefinition hook, &lt;br /&gt;
                                            MethodFeatures features, &lt;br /&gt;
                                            params FieldDefinition[] memberReferences);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The parameter description is the following:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;target&amp;lt;/code&amp;gt; || The method definition of the method which is to be hooked.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || The type (class/struct) that possesses the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; || The criteria by which the hook method should be chosen. Defines the structure of the hook method. Refer to the next subsection for more information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memberReferences&amp;lt;/code&amp;gt; || If one of the criteria is &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt;, specifies the fields that are to be passed to the method.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;hook&amp;lt;/code&amp;gt; || Method definition of the hook method.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
While using the methods, note the following:&lt;br /&gt;
* When using &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, the final &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; might be different from the ones specified. That is simply because the method adapts to its passed parameters to find the best hook method.&lt;br /&gt;
However, the method attempts to find the best hook without throwing any exceptions (for the exception of &amp;lt;code&amp;gt;ArgumentException&amp;lt;/code&amp;gt; if the provided member fields do not belong to the target type).&lt;br /&gt;
* &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt; strictly checks whether the provided target and hook are injectable. If a discrepancy is found, the method will throw an exception containing the reason the method failed.&lt;br /&gt;
* Prefer using &amp;lt;code&amp;gt;GetHookMethod&amp;lt;/code&amp;gt;, as it mostly exception-free and will return either a working instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Method Features ====&lt;br /&gt;
To allow the developer to freely choose which kind of hook to use, what parameters to pass and what to return, ReiPatcherPlus allows to specify certain criteria that define the layot of the hook method.&lt;br /&gt;
Albeit allowing different set of parameters to be passed, the hook method must have its parameters in a certain order for ReiPatcherPlus to work with them.&lt;br /&gt;
&lt;br /&gt;
Below is the hook method template with numbered positions and a table of what types are allowed in place of those positions and which &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; fields to use to enable those positions:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static &amp;lt;2.1&amp;gt; MyHookMethod(&amp;lt;1&amp;gt;, &amp;lt;2.2&amp;gt;, &amp;lt;3&amp;gt;, &amp;lt;4&amp;gt;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; field !! Position value replacement, if feature specified (only types and prefixes specified) !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.None&amp;lt;/code&amp;gt; || &amp;lt;1&amp;gt;, &amp;lt;2.2&amp;gt;, &amp;lt;3&amp;gt;, &amp;lt;4&amp;gt; = Empty&amp;lt;br/&amp;gt;&amp;lt;2.1&amp;gt; = &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; || The method may not have any of the features.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassTargetType&amp;lt;/code&amp;gt; || &amp;lt;1&amp;gt; = Target type || The method may be passed a reference to the target type that initially called the hooked method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; || &amp;lt;2.1&amp;gt; = &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;If target has a return type:&amp;lt;br/&amp;gt;&amp;lt;2.2&amp;gt; = &amp;lt;code&amp;gt;out &amp;lt;return type&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;Otherwise:&amp;lt;br/&amp;gt;&amp;lt;2.2&amp;gt; = Empty || The hook method is a redirect and thus may be passed a reference to the return value (if there is such). If the the target method has a return value of type &amp;lt;code&amp;gt;&amp;lt;return type&amp;gt;&amp;lt;/code&amp;gt;, a parameter of the same type is passed as a reference to the hook method.&amp;lt;br/&amp;gt;'''Note:''' If the feature is not specified, &amp;lt;2.1&amp;gt; must be &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt; || &amp;lt;3&amp;gt; = &amp;lt;code&amp;gt;ref &amp;lt;type1&amp;gt;, ref &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass references to the target type's member fields (assuming target method is not static) specified by the &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; creation method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMethodParametersByValue&amp;lt;/code&amp;gt; || &amp;lt;4&amp;gt; = &amp;lt;code&amp;gt;&amp;lt;type1&amp;gt;, &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass its own parameters to the hook. Since they are passed by value, they cannot be altered.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.PassMethodParametersByReference&amp;lt;/code&amp;gt; || &amp;lt;4&amp;gt; = &amp;lt;code&amp;gt;ref &amp;lt;type1&amp;gt;, ref &amp;lt;type2&amp;gt;, ...&amp;lt;/code&amp;gt; || The method may pass its own parameters to the hook. Since they are passed by reference, they can be altered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Some important things to point out:&lt;br /&gt;
* The hook method '''must''' be public and static! Otherwise it is impossible to hook it anywhere.&lt;br /&gt;
* Some of the above-mentioned features can be left out. However the order of the parameters must be always preserved!&lt;br /&gt;
* If &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; is set, the hook method must return a &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the hook method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the execution of the original target method's instructions is interrupted; the target method simply returns the result value it got from the hook method (if any). In the contrary, if the hook method return &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the original target method will continue its execution after the hook method has completed executing its instructions.&lt;br /&gt;
* Legacy notice: &amp;lt;code&amp;gt;MethodFeatures.PassReturn&amp;lt;/code&amp;gt; makes ReiPatcherPlus search for a redirect method. However, since both hooking and redirecting have been combined into one single method, there is no point in differentiating between them anymore.&lt;br /&gt;
&lt;br /&gt;
The features may be combined with a logical OR operator (&amp;lt;code&amp;gt;|&amp;lt;/code&amp;gt;). In addition to the features above, the &amp;lt;code&amp;gt;MethodFeatures&amp;lt;/code&amp;gt; enumeration has the following feature combinations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Feature !! Combination equivalent&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.All_ByValue&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;MethodFeatures.PassTargetType | MethodFeatures.PassReturn | MethodFeatures.PassMemberReferences | MethodFeatures.PassMethodParametersByValue&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodFeatures.All_ByReference&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;MethodFeatures.PassTargetType | MethodFeatures.PassReturn | MethodFeatures.PassMemberReferences | MethodFeatures.PassMethodParametersByReference&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 // Getting type definition for the class that contains all the hook methods&lt;br /&gt;
 TypeDefinition hookType = HookModule.GetType(&amp;quot;MyHookNamespace.Hook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 MethodDefinition m2 = swallowType.GetMethod(&amp;quot;MakeFly&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
 // Valid hook method prototype: public static void GetNeededSwallowsHook1()&lt;br /&gt;
 MethodHook hookM1 = this.GetHookMethod(m1, &lt;br /&gt;
                                        hookType, &lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook1&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.None);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool GetNeededSwallowsHook2(Swallow self, out float result, int coconuts)&lt;br /&gt;
 MethodHook hookM2 = this.GetHookMethod(m1,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook2&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByValue);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool GetNeededSwallowsHook3(Swallow self, out float result, ref int coconuts)									&lt;br /&gt;
 MethodHook hookM3 = this.GetHookMethod(m1,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook3&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByReference);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool MakeFlyHook(Swallow self, out float result, ref float airSpeedVelocity, int coconuts)									&lt;br /&gt;
 MethodHook hookM4 = this.GetHookMethod(m2,&lt;br /&gt;
                                        hookType,&lt;br /&gt;
                                        &amp;quot;MakeFlyHook&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.PassTargetType&lt;br /&gt;
                                        | MethodFeatures.PassReturn&lt;br /&gt;
                                        | MethodFeatures.PassMemberReferences&lt;br /&gt;
                                        | MethodFeatures.PassMethodParametersByValue,&lt;br /&gt;
                                        swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;));&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition hookMethod = hookType.GetMethod(&amp;quot;MakeFlyHook2&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method: public static bool MakeFlyHook(Swallow self, out float result, ref float airSpeedVelocity, ref int coconuts)									&lt;br /&gt;
 MethodHook hookM5 = MethodHook.FromMethodDefinition(m2,&lt;br /&gt;
                                                     hookMethod,&lt;br /&gt;
                                                     MethodFeatures.All_ByReference,&lt;br /&gt;
                                                     swallowType.GetField(&amp;quot;airSpeedVelocity&amp;quot;))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Injecting the methods ===&lt;br /&gt;
Finally, ReiPatcherPlus provides a functionality to patch methods. That can be done with &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
The exact definitions and parameter descriptions are below:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void AttachMethod(MethodHook hook, int codeOffset, InjectDirection dir);&lt;br /&gt;
 void AttachMethod(MethodDefinition target, &lt;br /&gt;
                   MethodDefinition hook, &lt;br /&gt;
                   int codeOffset, &lt;br /&gt;
                   MethodFeatures features, &lt;br /&gt;
                   InjectDirection dir,&lt;br /&gt;
                   params FieldDefinition[] memberReferences);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;target&amp;lt;/code&amp;gt; || The method definition of the method which is to be hooked.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MethodDefinition hook&amp;lt;/code&amp;gt; || Method definition of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;features&amp;lt;/code&amp;gt; || The criteria by which the hook method should be chosen. Defines the structure of the hook method. '''Default: ''' &amp;lt;code&amp;gt;MethodFeatures.None&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memberReferences&amp;lt;/code&amp;gt; || If one of the criteria is &amp;lt;code&amp;gt;MethodFeatures.PassMemberReferences&amp;lt;/code&amp;gt;, specifies the fields that are to be passed to the method.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;MethodHook hook&amp;lt;/code&amp;gt; || An instance of &amp;lt;code&amp;gt;MethodHook&amp;lt;/code&amp;gt; that contains all the appropriate information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;codeOffset&amp;lt;/code&amp;gt; || An index value of an IL instruction in the target method from which to begin injection. If set to negative, will begin counting from the last instruction of the target method, where -1 is being the last instruction.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;dir&amp;lt;/code&amp;gt; || Direction in which to inject the hook method. If &amp;lt;code&amp;gt;InjectDirection.Before&amp;lt;/code&amp;gt;, will inject the hook method before the specified instruction. If &amp;lt;code&amp;gt;InjectDirection.After&amp;lt;/code&amp;gt;, the injection will commence after the provided instruction. '''Default:''' &amp;lt;code&amp;gt;InjectDirection.Before&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Elementary, these two methods will automatically inject the needed CIL instructions depending on the chosen hook/target method.&amp;lt;br/&amp;gt;&lt;br /&gt;
The latter method will verify the compatibility between the target and the hook before applying the patch. That method is equivalent to calling &amp;lt;code&amp;gt;MethodHook.FromMethodDefinition&amp;lt;/code&amp;gt; and then &amp;lt;code&amp;gt;AttachMethod&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Most of the time setting code offset to 0 will be sufficient for plug-ins. However, if one wants to place the hook at a certain place, refer to the previous sections on how to decompile the .NET code. Most of the decompilers come with IL decompilers bundled (like ILSpy), which allows to inspect pure IL instructions to find the perfect attachment point.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 TypeDefinition swallowType = MyModule.GetType(&amp;quot;Game.Swallow&amp;quot;);&lt;br /&gt;
 TypeDefinition hookType = HookModule.GetType(&amp;quot;MyHookNamespace.Hook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 MethodDefinition m1 = swallowType.GetMethod(&amp;quot;GetNeededSwallows&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // Valid hook method prototype: public static void GetNeededSwallowsHook1()&lt;br /&gt;
 MethodHook hookM1 = this.GetHookMethod(m1, &lt;br /&gt;
                                        hookType, &lt;br /&gt;
                                        &amp;quot;GetNeededSwallowsHook1&amp;quot;,&lt;br /&gt;
                                        MethodFeatures.None);&lt;br /&gt;
 &lt;br /&gt;
 this.AttachMethod(hookM1, 0);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Debugging functions ===&lt;br /&gt;
ReiPatcherPlus provides simple methods for patcher message logging. All of the logging methods are located in &amp;lt;code&amp;gt;RPPLogger&amp;lt;/code&amp;gt; class.&lt;br /&gt;
&lt;br /&gt;
However, to enable logging, one must use the DEV version of the ReiPatcherPlus (slightly larger file size than normal ReiPatcherPlus).&lt;br /&gt;
After that, one can set &amp;lt;code&amp;gt;RPPLogger.VERBOSE_LEVEL&amp;lt;/code&amp;gt; variable to enable logging of certain methods.&lt;br /&gt;
&lt;br /&gt;
Possible variable values are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.None&amp;lt;/code&amp;gt; || Don't output any messages&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.Patcher&amp;lt;/code&amp;gt; || Output patcher-related messages (getting hook methods, attaching methods, etc.).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RPPLogger.VerboseLevel.Cecil&amp;lt;/code&amp;gt; || Output Mono.Cecil-related extension method messages. Includes parameter equality checking and method searching.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The flags can be combined with a logical OR (&amp;lt;code&amp;gt;|&amp;lt;/code&amp;gt;) operator.&lt;br /&gt;
&lt;br /&gt;
If one whishes to output own logging messages, it is possible through the following methods located in &amp;lt;code&amp;gt;RPPLogger&amp;gt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void Log(string message, VerboseLevel level, bool addPrefix);&lt;br /&gt;
 void LogLine(string message, VerboseLevel level, bool addPrefix);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And the parameters:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt; || Message to output.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; || The level to output the message to. Used to filter the output based on selected levels.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;addPrefix&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will append a prefix specified on &amp;lt;code&amp;gt;RPPLogger.PREFIX&amp;lt;/code&amp;gt; before the specified &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The difference between the methods is that the latter will add a line break to the message, while the former one will not.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Set verbose level to patcher only&lt;br /&gt;
 RPPLogger.VERBOSE_LEVEL = RPPLogger.VerboseLevel.Patcher;&lt;br /&gt;
 &lt;br /&gt;
 // Will be shown in ReiPatcher console&lt;br /&gt;
 RPPLogger.LogLine(&amp;quot;Hello, log!&amp;quot;, RPPLogger.VerboseLevel.Patcher);&lt;br /&gt;
 &lt;br /&gt;
 // Won't be seen in ReiPatcher&lt;br /&gt;
 RPPLogger.LogLine(&amp;quot;I am hidden!&amp;quot;, RPPLogger.VerboseLevel.Cecil);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Legacy and other obsolete methods ===&lt;br /&gt;
These methods are marked as obsolete and must not be used. Instead, use the newer functionality of ReiPatcherPlus.&lt;br /&gt;
&lt;br /&gt;
==== Method hooking ====&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Method redirecting ====&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18008</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18008"/>
				<updated>2015-08-07T16:01:27Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: /* Patching phase */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This tutorial was written with ReiPatcher 0.9.0.6 and UnityInjector 1.0.1.1. It is possible that in later versions of those tool there will have been some major changes in their design, which may or may not make this tutorial obsolete.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be almost impossible to manipulate, which is due to the code being mostly unmanaged (notice that the managed code is still compiled into CIL, albeit with &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt; tag.).&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2x84_Data\Managed&amp;lt;/code&amp;gt; folder at the very least).&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Designing the plug-in ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good programming choice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies.&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
Every assembly that one wishes to be patched must be requested. Otherwise it might not be included into the patching cycle.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times and on the right assemblies.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if it has already been patched by our patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
The contents of the method depend on the situation. However, in almost all cases patching requires using various methods provided by Mono.Cecil to alter the contents of classes and methods.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, why not do all that with just two lines of code?&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;), &amp;quot;OnClick&amp;quot;,&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL (using UnityInjector) ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehaviour&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that the name of plug-in's INI configuration file will be the same as plug-in class name. In our case, calling &amp;lt;code&amp;gt;SaveConfig()&amp;lt;/code&amp;gt; will create a configuration file named &amp;lt;code&amp;gt;HelloWorldPlugin.ini&amp;lt;/code&amp;gt; which will be saved to &amp;lt;code&amp;gt;&amp;lt;Game's main directory&amp;gt;\UnityInjector\Config&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command above&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
=== Method hooking ===&lt;br /&gt;
Consider the following class that contains the following methods:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class GameClass&lt;br /&gt;
     {&lt;br /&gt;
         public int numberOfCarrots = 42;&lt;br /&gt;
         &lt;br /&gt;
         public void GameMethod();&lt;br /&gt;
         public void GameMethod(string s, int i, bool b);&lt;br /&gt;
         private void GameMethod(byte b);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now imagine we want to do the simplest of tasks: alter &amp;lt;code&amp;gt;GameMethod()&amp;lt;/code&amp;gt; so that it calls our own method &amp;lt;code&amp;gt;MyMethod()&amp;lt;/code&amp;gt; that is located in our own assembly in namespace &amp;lt;code&amp;gt;MyNamespace.MyClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In this case we can use &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;, a method that injects (hooks) a call to &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; (hook method) before the method's own instructions. That way, before &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; proceeds with own logic, it will call &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
Suppose we are patching &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; assembly. Assume also that we have &amp;lt;code&amp;gt;AssemblyDefinition&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;MyNamespace&amp;lt;/code&amp;gt; assembly as a variable named &amp;lt;code&amp;gt;hookAssembly&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Therefore, we can patch the methods in patcher class's &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod()&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame, string s, int i, bool b) &lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(string), typeof(int), typeof(bool) },&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(byte b)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(byte) }, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that only the ones with &amp;lt;code&amp;gt;Game.GameClass&amp;lt;/code&amp;gt; object will be able to access the &amp;lt;code&amp;gt;numberOfCarrots&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
=== Method redirecting ===&lt;br /&gt;
Let us consider the next class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         public float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suppose we want not to just hook a method — we want to replace it with a definition of our own! That can be achieved with ReiPatcherPlus' &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; methods.&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
With the same rules as before, here is the code that is put into &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 			 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, bool isUnladen, float distance)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;MakeFly&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool), typeof(float) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result, int coconuts)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;,&lt;br /&gt;
                     new[] { typeof(int) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18007</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18007"/>
				<updated>2015-08-07T15:57:39Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: /* Manipulating INI files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This tutorial was written with ReiPatcher 0.9.0.6 and UnityInjector 1.0.1.1. It is possible that in later versions of those tool there will have been some major changes in their design, which may or may not make this tutorial obsolete.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be almost impossible to manipulate, which is due to the code being mostly unmanaged (notice that the managed code is still compiled into CIL, albeit with &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt; tag.).&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2x84_Data\Managed&amp;lt;/code&amp;gt; folder at the very least).&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Designing the plug-in ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good programming choice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies.&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
Every assembly that one wishes to be patched must be requested. Otherwise it might not be included into the patching cycle.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times and on the right assemblies.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if it has already been patched by our patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, why not do all that with just two lines of code?&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;), &amp;quot;OnClick&amp;quot;,&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL (using UnityInjector) ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehaviour&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note, that the name of plug-in's INI configuration file will be the same as plug-in class name. In our case, calling &amp;lt;code&amp;gt;SaveConfig()&amp;lt;/code&amp;gt; will create a configuration file named &amp;lt;code&amp;gt;HelloWorldPlugin.ini&amp;lt;/code&amp;gt; which will be saved to &amp;lt;code&amp;gt;&amp;lt;Game's main directory&amp;gt;\UnityInjector\Config&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command above&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
=== Method hooking ===&lt;br /&gt;
Consider the following class that contains the following methods:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class GameClass&lt;br /&gt;
     {&lt;br /&gt;
         public int numberOfCarrots = 42;&lt;br /&gt;
         &lt;br /&gt;
         public void GameMethod();&lt;br /&gt;
         public void GameMethod(string s, int i, bool b);&lt;br /&gt;
         private void GameMethod(byte b);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now imagine we want to do the simplest of tasks: alter &amp;lt;code&amp;gt;GameMethod()&amp;lt;/code&amp;gt; so that it calls our own method &amp;lt;code&amp;gt;MyMethod()&amp;lt;/code&amp;gt; that is located in our own assembly in namespace &amp;lt;code&amp;gt;MyNamespace.MyClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In this case we can use &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;, a method that injects (hooks) a call to &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; (hook method) before the method's own instructions. That way, before &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; proceeds with own logic, it will call &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
Suppose we are patching &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; assembly. Assume also that we have &amp;lt;code&amp;gt;AssemblyDefinition&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;MyNamespace&amp;lt;/code&amp;gt; assembly as a variable named &amp;lt;code&amp;gt;hookAssembly&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Therefore, we can patch the methods in patcher class's &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod()&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame, string s, int i, bool b) &lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(string), typeof(int), typeof(bool) },&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(byte b)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(byte) }, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that only the ones with &amp;lt;code&amp;gt;Game.GameClass&amp;lt;/code&amp;gt; object will be able to access the &amp;lt;code&amp;gt;numberOfCarrots&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
=== Method redirecting ===&lt;br /&gt;
Let us consider the next class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         public float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suppose we want not to just hook a method — we want to replace it with a definition of our own! That can be achieved with ReiPatcherPlus' &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; methods.&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
With the same rules as before, here is the code that is put into &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 			 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, bool isUnladen, float distance)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;MakeFly&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool), typeof(float) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result, int coconuts)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;,&lt;br /&gt;
                     new[] { typeof(int) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18006</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18006"/>
				<updated>2015-08-07T15:52:39Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: /* Writing the plug-in DLL */ Altered the name of the section to find it easily&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This tutorial was written with ReiPatcher 0.9.0.6 and UnityInjector 1.0.1.1. It is possible that in later versions of those tool there will have been some major changes in their design, which may or may not make this tutorial obsolete.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be almost impossible to manipulate, which is due to the code being mostly unmanaged (notice that the managed code is still compiled into CIL, albeit with &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt; tag.).&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2x84_Data\Managed&amp;lt;/code&amp;gt; folder at the very least).&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Designing the plug-in ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good programming choice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies.&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
Every assembly that one wishes to be patched must be requested. Otherwise it might not be included into the patching cycle.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times and on the right assemblies.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if it has already been patched by our patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, why not do all that with just two lines of code?&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;), &amp;quot;OnClick&amp;quot;,&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL (using UnityInjector) ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehaviour&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create a one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command above&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
=== Method hooking ===&lt;br /&gt;
Consider the following class that contains the following methods:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class GameClass&lt;br /&gt;
     {&lt;br /&gt;
         public int numberOfCarrots = 42;&lt;br /&gt;
         &lt;br /&gt;
         public void GameMethod();&lt;br /&gt;
         public void GameMethod(string s, int i, bool b);&lt;br /&gt;
         private void GameMethod(byte b);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now imagine we want to do the simplest of tasks: alter &amp;lt;code&amp;gt;GameMethod()&amp;lt;/code&amp;gt; so that it calls our own method &amp;lt;code&amp;gt;MyMethod()&amp;lt;/code&amp;gt; that is located in our own assembly in namespace &amp;lt;code&amp;gt;MyNamespace.MyClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In this case we can use &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;, a method that injects (hooks) a call to &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; (hook method) before the method's own instructions. That way, before &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; proceeds with own logic, it will call &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
Suppose we are patching &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; assembly. Assume also that we have &amp;lt;code&amp;gt;AssemblyDefinition&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;MyNamespace&amp;lt;/code&amp;gt; assembly as a variable named &amp;lt;code&amp;gt;hookAssembly&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Therefore, we can patch the methods in patcher class's &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod()&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame, string s, int i, bool b) &lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(string), typeof(int), typeof(bool) },&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(byte b)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(byte) }, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that only the ones with &amp;lt;code&amp;gt;Game.GameClass&amp;lt;/code&amp;gt; object will be able to access the &amp;lt;code&amp;gt;numberOfCarrots&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
=== Method redirecting ===&lt;br /&gt;
Let us consider the next class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         public float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suppose we want not to just hook a method — we want to replace it with a definition of our own! That can be achieved with ReiPatcherPlus' &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; methods.&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
With the same rules as before, here is the code that is put into &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 			 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, bool isUnladen, float distance)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;MakeFly&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool), typeof(float) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result, int coconuts)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;,&lt;br /&gt;
                     new[] { typeof(int) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18005</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18005"/>
				<updated>2015-08-07T15:51:31Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: /* Writing the plug-in DLL */ Fixed the name of MonoBehaviour class&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This tutorial was written with ReiPatcher 0.9.0.6 and UnityInjector 1.0.1.1. It is possible that in later versions of those tool there will have been some major changes in their design, which may or may not make this tutorial obsolete.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be almost impossible to manipulate, which is due to the code being mostly unmanaged (notice that the managed code is still compiled into CIL, albeit with &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt; tag.).&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2x84_Data\Managed&amp;lt;/code&amp;gt; folder at the very least).&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Designing the plug-in ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good programming choice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies.&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
Every assembly that one wishes to be patched must be requested. Otherwise it might not be included into the patching cycle.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times and on the right assemblies.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if it has already been patched by our patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, why not do all that with just two lines of code?&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;), &amp;quot;OnClick&amp;quot;,&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehaviour&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create a one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command above&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
=== Method hooking ===&lt;br /&gt;
Consider the following class that contains the following methods:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class GameClass&lt;br /&gt;
     {&lt;br /&gt;
         public int numberOfCarrots = 42;&lt;br /&gt;
         &lt;br /&gt;
         public void GameMethod();&lt;br /&gt;
         public void GameMethod(string s, int i, bool b);&lt;br /&gt;
         private void GameMethod(byte b);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now imagine we want to do the simplest of tasks: alter &amp;lt;code&amp;gt;GameMethod()&amp;lt;/code&amp;gt; so that it calls our own method &amp;lt;code&amp;gt;MyMethod()&amp;lt;/code&amp;gt; that is located in our own assembly in namespace &amp;lt;code&amp;gt;MyNamespace.MyClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In this case we can use &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;, a method that injects (hooks) a call to &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; (hook method) before the method's own instructions. That way, before &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; proceeds with own logic, it will call &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
Suppose we are patching &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; assembly. Assume also that we have &amp;lt;code&amp;gt;AssemblyDefinition&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;MyNamespace&amp;lt;/code&amp;gt; assembly as a variable named &amp;lt;code&amp;gt;hookAssembly&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Therefore, we can patch the methods in patcher class's &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod()&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame, string s, int i, bool b) &lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(string), typeof(int), typeof(bool) },&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(byte b)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(byte) }, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that only the ones with &amp;lt;code&amp;gt;Game.GameClass&amp;lt;/code&amp;gt; object will be able to access the &amp;lt;code&amp;gt;numberOfCarrots&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
=== Method redirecting ===&lt;br /&gt;
Let us consider the next class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         public float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suppose we want not to just hook a method — we want to replace it with a definition of our own! That can be achieved with ReiPatcherPlus' &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; methods.&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
With the same rules as before, here is the code that is put into &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 			 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, bool isUnladen, float distance)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;MakeFly&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool), typeof(float) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result, int coconuts)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;,&lt;br /&gt;
                     new[] { typeof(int) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18004</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18004"/>
				<updated>2015-08-07T09:42:00Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: /* Pre-patching checks */ Added a minor explanation.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This tutorial was written with ReiPatcher 0.9.0.6 and UnityInjector 1.0.1.1. It is possible that in later versions of those tool there will have been some major changes in their design, which may or may not make this tutorial obsolete.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be almost impossible to manipulate, which is due to the code being mostly unmanaged (notice that the managed code is still compiled into CIL, albeit with &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt; tag.).&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2x84_Data\Managed&amp;lt;/code&amp;gt; folder at the very least).&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Designing the plug-in ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good programming choice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies.&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
Every assembly that one wishes to be patched must be requested. Otherwise it might not be included into the patching cycle.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times and on the right assemblies.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if it has already been patched by our patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, why not do all that with just two lines of code?&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;), &amp;quot;OnClick&amp;quot;,&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehavior&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create a one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command above&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
=== Method hooking ===&lt;br /&gt;
Consider the following class that contains the following methods:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class GameClass&lt;br /&gt;
     {&lt;br /&gt;
         public int numberOfCarrots = 42;&lt;br /&gt;
         &lt;br /&gt;
         public void GameMethod();&lt;br /&gt;
         public void GameMethod(string s, int i, bool b);&lt;br /&gt;
         private void GameMethod(byte b);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now imagine we want to do the simplest of tasks: alter &amp;lt;code&amp;gt;GameMethod()&amp;lt;/code&amp;gt; so that it calls our own method &amp;lt;code&amp;gt;MyMethod()&amp;lt;/code&amp;gt; that is located in our own assembly in namespace &amp;lt;code&amp;gt;MyNamespace.MyClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In this case we can use &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;, a method that injects (hooks) a call to &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; (hook method) before the method's own instructions. That way, before &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; proceeds with own logic, it will call &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
Suppose we are patching &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; assembly. Assume also that we have &amp;lt;code&amp;gt;AssemblyDefinition&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;MyNamespace&amp;lt;/code&amp;gt; assembly as a variable named &amp;lt;code&amp;gt;hookAssembly&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Therefore, we can patch the methods in patcher class's &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod()&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame, string s, int i, bool b) &lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(string), typeof(int), typeof(bool) },&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(byte b)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(byte) }, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that only the ones with &amp;lt;code&amp;gt;Game.GameClass&amp;lt;/code&amp;gt; object will be able to access the &amp;lt;code&amp;gt;numberOfCarrots&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
=== Method redirecting ===&lt;br /&gt;
Let us consider the next class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         public float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suppose we want not to just hook a method — we want to replace it with a definition of our own! That can be achieved with ReiPatcherPlus' &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; methods.&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
With the same rules as before, here is the code that is put into &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 			 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, bool isUnladen, float distance)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;MakeFly&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool), typeof(float) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result, int coconuts)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;,&lt;br /&gt;
                     new[] { typeof(int) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18003</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18003"/>
				<updated>2015-08-07T09:40:02Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: /* Pre-patching phase */ Rephrased a sentence concerning the number of RequestAssembly calls&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This tutorial was written with ReiPatcher 0.9.0.6 and UnityInjector 1.0.1.1. It is possible that in later versions of those tool there will have been some major changes in their design, which may or may not make this tutorial obsolete.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be almost impossible to manipulate, which is due to the code being mostly unmanaged (notice that the managed code is still compiled into CIL, albeit with &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt; tag.).&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2x84_Data\Managed&amp;lt;/code&amp;gt; folder at the very least).&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Designing the plug-in ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good programming choice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies.&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
Every assembly that one wishes to be patched must be requested. Otherwise it might not be included into the patching cycle.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if it has already been patched by our patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, why not do all that with just two lines of code?&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;), &amp;quot;OnClick&amp;quot;,&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehavior&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create a one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command above&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
=== Method hooking ===&lt;br /&gt;
Consider the following class that contains the following methods:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class GameClass&lt;br /&gt;
     {&lt;br /&gt;
         public int numberOfCarrots = 42;&lt;br /&gt;
         &lt;br /&gt;
         public void GameMethod();&lt;br /&gt;
         public void GameMethod(string s, int i, bool b);&lt;br /&gt;
         private void GameMethod(byte b);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now imagine we want to do the simplest of tasks: alter &amp;lt;code&amp;gt;GameMethod()&amp;lt;/code&amp;gt; so that it calls our own method &amp;lt;code&amp;gt;MyMethod()&amp;lt;/code&amp;gt; that is located in our own assembly in namespace &amp;lt;code&amp;gt;MyNamespace.MyClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In this case we can use &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;, a method that injects (hooks) a call to &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; (hook method) before the method's own instructions. That way, before &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; proceeds with own logic, it will call &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
Suppose we are patching &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; assembly. Assume also that we have &amp;lt;code&amp;gt;AssemblyDefinition&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;MyNamespace&amp;lt;/code&amp;gt; assembly as a variable named &amp;lt;code&amp;gt;hookAssembly&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Therefore, we can patch the methods in patcher class's &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod()&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame, string s, int i, bool b) &lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(string), typeof(int), typeof(bool) },&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(byte b)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(byte) }, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that only the ones with &amp;lt;code&amp;gt;Game.GameClass&amp;lt;/code&amp;gt; object will be able to access the &amp;lt;code&amp;gt;numberOfCarrots&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
=== Method redirecting ===&lt;br /&gt;
Let us consider the next class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         public float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suppose we want not to just hook a method — we want to replace it with a definition of our own! That can be achieved with ReiPatcherPlus' &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; methods.&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
With the same rules as before, here is the code that is put into &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 			 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, bool isUnladen, float distance)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;MakeFly&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool), typeof(float) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result, int coconuts)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;,&lt;br /&gt;
                     new[] { typeof(int) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18002</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=18002"/>
				<updated>2015-08-07T09:30:48Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This tutorial was written with ReiPatcher 0.9.0.6 and UnityInjector 1.0.1.1. It is possible that in later versions of those tool there will have been some major changes in their design, which may or may not make this tutorial obsolete.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be almost impossible to manipulate, which is due to the code being mostly unmanaged (notice that the managed code is still compiled into CIL, albeit with &amp;lt;code&amp;gt;unsafe&amp;lt;/code&amp;gt; tag.).&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2x84_Data\Managed&amp;lt;/code&amp;gt; folder at the very least).&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Designing the plug-in ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good programming choice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies.&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
The number of requests is the same as the number of assemblies we want to patch.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if it has already been patched by our patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, why not do all that with just two lines of code?&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;), &amp;quot;OnClick&amp;quot;,&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehavior&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create a one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command above&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
=== Method hooking ===&lt;br /&gt;
Consider the following class that contains the following methods:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class GameClass&lt;br /&gt;
     {&lt;br /&gt;
         public int numberOfCarrots = 42;&lt;br /&gt;
         &lt;br /&gt;
         public void GameMethod();&lt;br /&gt;
         public void GameMethod(string s, int i, bool b);&lt;br /&gt;
         private void GameMethod(byte b);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now imagine we want to do the simplest of tasks: alter &amp;lt;code&amp;gt;GameMethod()&amp;lt;/code&amp;gt; so that it calls our own method &amp;lt;code&amp;gt;MyMethod()&amp;lt;/code&amp;gt; that is located in our own assembly in namespace &amp;lt;code&amp;gt;MyNamespace.MyClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In this case we can use &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;, a method that injects (hooks) a call to &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; (hook method) before the method's own instructions. That way, before &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; proceeds with own logic, it will call &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
Suppose we are patching &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; assembly. Assume also that we have &amp;lt;code&amp;gt;AssemblyDefinition&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;MyNamespace&amp;lt;/code&amp;gt; assembly as a variable named &amp;lt;code&amp;gt;hookAssembly&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Therefore, we can patch the methods in patcher class's &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod()&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame, string s, int i, bool b) &lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(string), typeof(int), typeof(bool) },&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(byte b)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(byte) }, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that only the ones with &amp;lt;code&amp;gt;Game.GameClass&amp;lt;/code&amp;gt; object will be able to access the &amp;lt;code&amp;gt;numberOfCarrots&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
=== Method redirecting ===&lt;br /&gt;
Let us consider the next class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         public float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suppose we want not to just hook a method — we want to replace it with a definition of our own! That can be achieved with ReiPatcherPlus' &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; methods.&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
With the same rules as before, here is the code that is put into &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 			 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, bool isUnladen, float distance)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;MakeFly&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool), typeof(float) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result, int coconuts)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;,&lt;br /&gt;
                     new[] { typeof(int) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=17999</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=17999"/>
				<updated>2015-08-07T08:17:44Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: Added more decompilers, changed directory info for ReiPatcher&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This tutorial was written with ReiPatcher 0.9.0.6 and UnityInjector 1.0.1.1. It is possible that in later versions of those tool there will have been some major changes in their design, which may or may not make this tutorial obsolete.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be impossible to manipulate, which is due to the code being mostly unmanaged.&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2x84_Data\Managed&amp;lt;/code&amp;gt; folder at the very least).&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* Basic knowledge of CIL (Common Intermediate Language). That is needed when writing own custom patches with Mono.Cecil.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy], [http://code.google.com/p/cecilstudio Cecil Studio], [https://www.jetbrains.com/decompiler/ dotPeek] (included in ReSharper by default, but this is the standalone version) and [http://www.red-gate.com/products/dotnet-development/reflector/ .NET Reflector] (paid, but includes patch testing tools like ILSpy). In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Designing the plug-in ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || ReiPatcher's install directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good programming choice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies.&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
The number of requests is the same as the number of assemblies we want to patch.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if it has already been patched by our patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, why not do all that with just two lines of code?&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;), &amp;quot;OnClick&amp;quot;,&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehavior&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Name if not specified.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
On UnityInjector 1.0.1.0 and newer, will now fallback to the Assembly Version if not specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create a one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command above&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
=== Method hooking ===&lt;br /&gt;
Consider the following class that contains the following methods:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class GameClass&lt;br /&gt;
     {&lt;br /&gt;
         public int numberOfCarrots = 42;&lt;br /&gt;
         &lt;br /&gt;
         public void GameMethod();&lt;br /&gt;
         public void GameMethod(string s, int i, bool b);&lt;br /&gt;
         private void GameMethod(byte b);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now imagine we want to do the simplest of tasks: alter &amp;lt;code&amp;gt;GameMethod()&amp;lt;/code&amp;gt; so that it calls our own method &amp;lt;code&amp;gt;MyMethod()&amp;lt;/code&amp;gt; that is located in our own assembly in namespace &amp;lt;code&amp;gt;MyNamespace.MyClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In this case we can use &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;, a method that injects (hooks) a call to &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; (hook method) before the method's own instructions. That way, before &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; proceeds with own logic, it will call &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
Suppose we are patching &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; assembly. Assume also that we have &amp;lt;code&amp;gt;AssemblyDefinition&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;MyNamespace&amp;lt;/code&amp;gt; assembly as a variable named &amp;lt;code&amp;gt;hookAssembly&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Therefore, we can patch the methods in patcher class's &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod()&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame, string s, int i, bool b) &lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(string), typeof(int), typeof(bool) },&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(byte b)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(byte) }, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that only the ones with &amp;lt;code&amp;gt;Game.GameClass&amp;lt;/code&amp;gt; object will be able to access the &amp;lt;code&amp;gt;numberOfCarrots&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
=== Method redirecting ===&lt;br /&gt;
Let us consider the next class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         public float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suppose we want not to just hook a method — we want to replace it with a definition of our own! That can be achieved with ReiPatcherPlus' &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; methods.&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
With the same rules as before, here is the code that is put into &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 			 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, bool isUnladen, float distance)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;MakeFly&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool), typeof(float) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result, int coconuts)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;,&lt;br /&gt;
                     new[] { typeof(int) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=17997</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=17997"/>
				<updated>2015-08-06T23:30:38Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: Mentioned the need of using this.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This tutorial was written with ReiPatcher 0.9.0.6 and UnityInjector 1.0.1.1. It is possible that in later versions of those tool there will have been some major changes in their design, which may or may not make this tutorial obsolete.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be impossible to manipulate, which is due to the code being mostly unmanaged.&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2x84_Data\Managed&amp;lt;/code&amp;gt; folder at the very least).&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy] and [http://code.google.com/p/cecilstudio Cecil Studio]. In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Designing the plug-in ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good programming choice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies.&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
The number of requests is the same as the number of assemblies we want to patch.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if it has already been patched by our patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, why not do all that with just two lines of code?&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;), &amp;quot;OnClick&amp;quot;,&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehavior&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create a one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command above&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
Note that accessing ReiPatcherPlus's methods requires one to use &amp;lt;code&amp;gt;this.&amp;lt;/code&amp;gt;, or the extension method's won't be seen.&lt;br /&gt;
&lt;br /&gt;
=== Method hooking ===&lt;br /&gt;
Consider the following class that contains the following methods:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class GameClass&lt;br /&gt;
     {&lt;br /&gt;
         public int numberOfCarrots = 42;&lt;br /&gt;
         &lt;br /&gt;
         public void GameMethod();&lt;br /&gt;
         public void GameMethod(string s, int i, bool b);&lt;br /&gt;
         private void GameMethod(byte b);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now imagine we want to do the simplest of tasks: alter &amp;lt;code&amp;gt;GameMethod()&amp;lt;/code&amp;gt; so that it calls our own method &amp;lt;code&amp;gt;MyMethod()&amp;lt;/code&amp;gt; that is located in our own assembly in namespace &amp;lt;code&amp;gt;MyNamespace.MyClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In this case we can use &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;, a method that injects (hooks) a call to &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; (hook method) before the method's own instructions. That way, before &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; proceeds with own logic, it will call &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
Suppose we are patching &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; assembly. Assume also that we have &amp;lt;code&amp;gt;AssemblyDefinition&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;MyNamespace&amp;lt;/code&amp;gt; assembly as a variable named &amp;lt;code&amp;gt;hookAssembly&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Therefore, we can patch the methods in patcher class's &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod()&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame, string s, int i, bool b) &lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(string), typeof(int), typeof(bool) },&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(byte b)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(byte) }, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that only the ones with &amp;lt;code&amp;gt;Game.GameClass&amp;lt;/code&amp;gt; object will be able to access the &amp;lt;code&amp;gt;numberOfCarrots&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
=== Method redirecting ===&lt;br /&gt;
Let us consider the next class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         public float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suppose we want not to just hook a method — we want to replace it with a definition of our own! That can be achieved with ReiPatcherPlus' &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; methods.&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
With the same rules as before, here is the code that is put into &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 			 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, bool isUnladen, float distance)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;MakeFly&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool), typeof(float) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result, int coconuts)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;,&lt;br /&gt;
                     new[] { typeof(int) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Template:Nav/Custom_Maid_3D2&amp;diff=17996</id>
		<title>Template:Nav/Custom Maid 3D2</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Template:Nav/Custom_Maid_3D2&amp;diff=17996"/>
				<updated>2015-08-06T23:27:50Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: Added link to Modding/Plugins&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* '''[[Custom Maid 3D 2/Gameplay|Gameplay]]'''&lt;br /&gt;
** [[Custom Maid 3D 2/Gameplay/H_Guide|H Guide]]&lt;br /&gt;
** [[Custom Maid 3D 2/Gameplay/Skills|Skills]]&lt;br /&gt;
** [[Custom Maid 3D 2/Gameplay/Maid_Classes|Maid Classes]]&lt;br /&gt;
** [[Custom Maid 3D 2/Gameplay/Characteristics|Characteristics]]&lt;br /&gt;
** [[Custom Maid 3D 2/Gameplay/VIP_Events|VIP Events]]&lt;br /&gt;
&lt;br /&gt;
* '''[[Custom Maid 3D 2/Technical Help|Technical Help]]'''&lt;br /&gt;
&lt;br /&gt;
* '''[[Custom Maid 3D 2/Modding|Modding]]'''&lt;br /&gt;
** [[Custom Maid 3D 2/Modding/Plugins|Writing plug-ins with ReiPatcher and UnityInjector]]&lt;br /&gt;
&lt;br /&gt;
* '''[[Custom Maid 3D 2/Version History|Version History]]'''&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=17995</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=17995"/>
				<updated>2015-08-06T23:26:23Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This tutorial was written with ReiPatcher 0.9.0.6 and UnityInjector 1.0.1.1. It is possible that in later versions of those tool there will have been some major changes in their design, which may or may not make this tutorial obsolete.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be impossible to manipulate, which is due to the code being mostly unmanaged.&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2x84_Data\Managed&amp;lt;/code&amp;gt; folder at the very least).&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3707606#post3707606 ReiPatcherPlus], which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy] and [http://code.google.com/p/cecilstudio Cecil Studio]. In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Designing the plug-in ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good programming choice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies.&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
The number of requests is the same as the number of assemblies we want to patch.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if it has already been patched by our patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, why not do all that with just two lines of code?&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;), &amp;quot;OnClick&amp;quot;,&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehavior&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create a one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command above&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
=== Method hooking ===&lt;br /&gt;
Consider the following class that contains the following methods:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class GameClass&lt;br /&gt;
     {&lt;br /&gt;
         public int numberOfCarrots = 42;&lt;br /&gt;
         &lt;br /&gt;
         public void GameMethod();&lt;br /&gt;
         public void GameMethod(string s, int i, bool b);&lt;br /&gt;
         private void GameMethod(byte b);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now imagine we want to do the simplest of tasks: alter &amp;lt;code&amp;gt;GameMethod()&amp;lt;/code&amp;gt; so that it calls our own method &amp;lt;code&amp;gt;MyMethod()&amp;lt;/code&amp;gt; that is located in our own assembly in namespace &amp;lt;code&amp;gt;MyNamespace.MyClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In this case we can use &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;, a method that injects (hooks) a call to &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; (hook method) before the method's own instructions. That way, before &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; proceeds with own logic, it will call &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
Suppose we are patching &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; assembly. Assume also that we have &amp;lt;code&amp;gt;AssemblyDefinition&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;MyNamespace&amp;lt;/code&amp;gt; assembly as a variable named &amp;lt;code&amp;gt;hookAssembly&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Therefore, we can patch the methods in patcher class's &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod()&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame, string s, int i, bool b) &lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(string), typeof(int), typeof(bool) },&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(byte b)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(byte) }, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that only the ones with &amp;lt;code&amp;gt;Game.GameClass&amp;lt;/code&amp;gt; object will be able to access the &amp;lt;code&amp;gt;numberOfCarrots&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
=== Method redirecting ===&lt;br /&gt;
Let us consider the next class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         public float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suppose we want not to just hook a method — we want to replace it with a definition of our own! That can be achieved with ReiPatcherPlus' &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; methods.&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
With the same rules as before, here is the code that is put into &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 			 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, bool isUnladen, float distance)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;MakeFly&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool), typeof(float) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result, int coconuts)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;,&lt;br /&gt;
                     new[] { typeof(int) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=17994</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=17994"/>
				<updated>2015-08-06T23:02:04Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Custom Maid 3D 2}}&lt;br /&gt;
&lt;br /&gt;
Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use ReiPatcherPlus, an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This tutorial was written with ReiPatcher 0.9.0.6 and UnityInjector 1.0.1.1. It is possible that in later versions of those tool there will have been some major changes in their design, which may or may not make this tutorial obsolete.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be impossible to manipulate, which is due to the code being mostly unmanaged.&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2x84_Data\Managed&amp;lt;/code&amp;gt; folder at the very least).&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* ReiPatcherPlus, which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy] and [http://code.google.com/p/cecilstudio Cecil Studio]. In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Designing the plug-in ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good programming choice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies.&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
The number of requests is the same as the number of assemblies we want to patch.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if it has already been patched by our patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, why not do all that with just two lines of code?&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;), &amp;quot;OnClick&amp;quot;,&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehavior&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create a one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command above&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
=== Method hooking ===&lt;br /&gt;
Consider the following class that contains the following methods:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class GameClass&lt;br /&gt;
     {&lt;br /&gt;
         public int numberOfCarrots = 42;&lt;br /&gt;
         &lt;br /&gt;
         public void GameMethod();&lt;br /&gt;
         public void GameMethod(string s, int i, bool b);&lt;br /&gt;
         private void GameMethod(byte b);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now imagine we want to do the simplest of tasks: alter &amp;lt;code&amp;gt;GameMethod()&amp;lt;/code&amp;gt; so that it calls our own method &amp;lt;code&amp;gt;MyMethod()&amp;lt;/code&amp;gt; that is located in our own assembly in namespace &amp;lt;code&amp;gt;MyNamespace.MyClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In this case we can use &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;, a method that injects (hooks) a call to &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; (hook method) before the method's own instructions. That way, before &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; proceeds with own logic, it will call &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
Suppose we are patching &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; assembly. Assume also that we have &amp;lt;code&amp;gt;AssemblyDefinition&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;MyNamespace&amp;lt;/code&amp;gt; assembly as a variable named &amp;lt;code&amp;gt;hookAssembly&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Therefore, we can patch the methods in patcher class's &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod()&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame, string s, int i, bool b) &lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(string), typeof(int), typeof(bool) },&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(byte b)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(byte) }, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that only the ones with &amp;lt;code&amp;gt;Game.GameClass&amp;lt;/code&amp;gt; object will be able to access the &amp;lt;code&amp;gt;numberOfCarrots&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
=== Method redirecting ===&lt;br /&gt;
Let us consider the next class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         public float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suppose we want not to just hook a method — we want to replace it with a definition of our own! That can be achieved with ReiPatcherPlus' &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; methods.&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
With the same rules as before, here is the code that is put into &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 			 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, bool isUnladen, float distance)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;MakeFly&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool), typeof(float) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result, int coconuts)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;,&lt;br /&gt;
                     new[] { typeof(int) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	<entry>
		<id>http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=17993</id>
		<title>Custom Maid 3D2/Modding/Plugins</title>
		<link rel="alternate" type="text/html" href="http://wiki.anime-sharing.com/hgames/index.php?title=Custom_Maid_3D2/Modding/Plugins&amp;diff=17993"/>
				<updated>2015-08-06T23:01:05Z</updated>
		
		<summary type="html">&lt;p&gt;Denikson: Created page with &amp;quot;Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's o...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Since Custom Maid 3D 2 was made using Unity Engine and scripted with .NET, it is possible to manipulate game's behaviour using .NET and some tools to inject code into game's own DLLs. &lt;br /&gt;
&lt;br /&gt;
In this tutorial we will be using [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher], a general-purpose .NET assembly patcher by HongFire user [http://www.hongfire.com/forum/member.php/1283907-usagirei usagirei], and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector], a simple plug-in injector, made by the same user, to create simple Unity plug-ins.&lt;br /&gt;
&lt;br /&gt;
To simplify code, this tutorial will also use ReiPatcherPlus, an extension library for ReiPatcher to provide a handful of convenient methods. If one prefers to manipulate assemblies oneself, the same results may be achieved with Mono.Cecil, which ReiPathcer and ReiPatcherPlus use as well.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' This tutorial was written with ReiPatcher 0.9.0.6 and UnityInjector 1.0.1.1. It is possible that in later versions of those tool there will have been some major changes in their design, which may or may not make this tutorial obsolete.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
=== About this tutorial ===&lt;br /&gt;
In this tutorial we will use ReiPatcher and UnityInjector to create a simple plug-in called ''HelloWorld'' which will print &amp;quot;Hello, world!&amp;quot; on the screen every time a button is pressed in the game. We will also implement the ability to stop printing the message with a press of a key.&lt;br /&gt;
&lt;br /&gt;
=== How ReiPatcher and UnityInjector work ===&lt;br /&gt;
While having some minor differences in purpose, both function as important tools to patch and manipulate CM3D2 (or any other .NET programs or Unity games).&lt;br /&gt;
==== ReiPatcher ====&lt;br /&gt;
ReiPatcher is an all-purpose tool for injecting CIL (Common Intermediate Language) instructions into existing managed assemblies and programs that were made using .NET. While the tool was initially made at the time of CM3D2, it is capable of patching almost any .NET assembly, as long as it is compiled into managed CIL, like C# and VB.NET do. Notice however, that C++/CLI assemblies might be impossible to manipulate, which is due to the code being mostly unmanaged.&lt;br /&gt;
By using ReiPatcher we can for instance hook methods (make them call other methods from outside their original assemblies) or even redirect them (make them use custom logic instead of game's original code). Furthermore, with the help of Mono.Cecil library, it is possible to add, remove and edit any original methods or assemblies without having to explicitly to decompile and recompile assemblies.&lt;br /&gt;
&lt;br /&gt;
As of this writing, ReiPatcher operates as follows. The programmer creates two DLLs: the one that contains custom hook or redirect methods, and the one that is used by ReiPatcher itself to patch the assemblies to call the custom methods. While the former DLL can have a structure of its own, the latter requires to have patcher classes (classes, that extend ReiPatcher.exe's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; class). Every class that extends &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; is considered a patch in itself, which means that the patch DLL can contain as many patches as the programmer wants.&lt;br /&gt;
&lt;br /&gt;
For further information on how to use ReiPatcher to hook or redirect methods, refer to the next sections of this tutorial.&lt;br /&gt;
&lt;br /&gt;
===== ReiPatcherPlus =====&lt;br /&gt;
ReiPatcher's purpose is to provide an API for easy code injection. However, while ReiPatcher manages patching, assembly manipulation itself must be implemented by the programmer with the help of Mono.Cecil.&lt;br /&gt;
Unfortunately, anything beyond injecting simple function calls increases the complexity of the code to the point where it is almost impossible to maintain it. &lt;br /&gt;
&lt;br /&gt;
Therefore, an extension for ReiPatcher was created to encapsulate the most common routine methods for patching, injecting and altering assembly members.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus allows to inject two types of functions:&lt;br /&gt;
* ''Hooks'': Methods which the injected function will call before continuing with its own routine&lt;br /&gt;
* ''Redirects'': Methods which the injected function will call. However, the return value of the redirect function determines whether the injected function will continue or return. That means that the redirect function can &amp;quot;redirect&amp;quot; game logic to programmer's own.&lt;br /&gt;
&lt;br /&gt;
In addition to injection, ReiPatcherPlus allows to easily change visibility of class members to public. Furthermore, it is possible to make methods virtual.&lt;br /&gt;
&lt;br /&gt;
This tutorial uses ReiPatcherPlus to shorten the code. Of course, full source code will be provided, where possible.&lt;br /&gt;
&lt;br /&gt;
==== UnityInjector ====&lt;br /&gt;
Sometimes one does not need to hook or redirect in-game methods, but instead just needs to manipulate in-game objects, like textures, buttons, models, cameras or input, every tick (game update, usualy called every 1/60th of a second). In that case, patching game's assemblies is not required; instead, UnityInjector can be used.&lt;br /&gt;
&lt;br /&gt;
UnityInjector is a plug-in manager, that hooks into a Unity Engine game and creates a game object of itself that is capable of being updated and accessing other game objects. In other words, UnityInjector uses ReiPatcher to be inserted into the game and allow programmers to create simple plug-ins without the need of patching any assemblies over and over again.&lt;br /&gt;
UnityInjector can be used to process user input, create new UI and change properties of objects that are loaded into the game.&lt;br /&gt;
&lt;br /&gt;
== Tools ==&lt;br /&gt;
=== Required ===&lt;br /&gt;
* Custom Maid 3D 2 (or just the DLLs found in &amp;lt;code&amp;gt;CM3D2x84_Data\Managed&amp;lt;/code&amp;gt; folder at the very least).&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector].&lt;br /&gt;
* .NET Framework 3.5 or later.&lt;br /&gt;
* IDE to program with a .NET-compatible language. Some of the more popular ones are [https://www.visualstudio.com/ Visual Studio] (VS2015 Community is free), [http://www.monodevelop.com/ MonoDevelop] and [http://www.icsharpcode.net/OpenSource/SD/ SharpDevelop]. This tutorial was initially written for Visual Studio.&lt;br /&gt;
* [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703144#post3703144 ReiPatcher] and [http://www.hongfire.com/forum/showthread.php/444101-%28KISS%29-Custom-Maid-3D-2?p=3703145#post3703145 UnityInjector]. Mono.Cecil is included in ReiPatcher and thus is not required to be downloaded by itself.&lt;br /&gt;
* Basic knowledge of at least one programming language that supports .NET Framework. This tutorial is written in C#, but the plug-ins may be written in VB.NET and other .NET-compliant languages alike.&lt;br /&gt;
&lt;br /&gt;
=== Additional ===&lt;br /&gt;
* ReiPatcherPlus, which provides methods to hook and redirect methods, load assemblies, etc.&lt;br /&gt;
* [https://www.jetbrains.com/resharper/ ReSharper] which is a productivity tool for Visual Studio. The tool provides for a more efficient and faster development.&lt;br /&gt;
* .NET decompiler to view game's original code, which will be needed to create own plug-ins. Such tools are, for instance, [http://www.ilspy.com/ ILSpy] and [http://code.google.com/p/cecilstudio Cecil Studio]. In this tutorial we will be using ILSpy.&lt;br /&gt;
&lt;br /&gt;
== Designing the plug-in ==&lt;br /&gt;
Before we can start programming, we need to gather information about how to implement our plug-in. For that, we will use ILSpy (alternatively, you can use any other .NET code viewer) to find the classes and methods to hook.&lt;br /&gt;
In the case of CM3D2, most important code is located in &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed\Assembly-CSharp.dll&amp;lt;/code&amp;gt;. To view the code with ILSpy, do the following:&lt;br /&gt;
# Download and fire up ILSpy.&lt;br /&gt;
# Click &amp;lt;code&amp;gt;File-&amp;gt;Open&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+O&amp;lt;/code&amp;gt;) and navigate to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (choose either x86 or x64 folder).&lt;br /&gt;
# Choose &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; and hit &amp;quot;Open&amp;quot;. That will add the library to the list of loaded ones.&lt;br /&gt;
# Click on the &amp;quot;+&amp;quot; button left to the loaded assembly to expand the view and see namespaces contained in the assembly.&lt;br /&gt;
&lt;br /&gt;
From here it is the programmer's task to find the class and method to hook or redirect. Sometimes it is not even necessary to hook anything at all, for manipulating in-game property with UnityInjector may do the trick. However, for the purpose of this tutorial we shall use ReiPatcher to hook methods nonetheless.&lt;br /&gt;
&lt;br /&gt;
While trying to find the needed classes or methods, one can use the following tools in ILSpy to simplify searching:&lt;br /&gt;
* Clicking on the &amp;quot;+&amp;quot; left to any item will expand it to show the sub-items. Namespaces expand into types (classes, structs, etc) and those expand into members (variables, methods, properties). Clicking on the type or its member will show its definition in C#, VB.NET or pure CIL depending on chosen settings.&lt;br /&gt;
* Right-clicking any item and choosing &amp;quot;Analyze&amp;quot; will bring up the &amp;quot;Analyzer&amp;quot; window which will contain such information as where the item is used, where it is defined or where it is exposed to other types. That will significantly speed up the process of finding methods to hook, redirect or use.&lt;br /&gt;
* Read the names and definitions, for most of the time they reveal the purpose of the type or the method.&lt;br /&gt;
&lt;br /&gt;
For the purpose of this tutorial, we can find that the class &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; in the general namespace (notated as &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; by ILSpy) has a method called &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt;. After looking at the definition and analysing the method we can be rather certain that this is the method we are looking for.&lt;br /&gt;
Therefore, by hooking the method (not redirecting — we'll discuss the difference later!) we can detect whether a button has been pressed. Now that we know what methods to hook, we can proceed to projects for ReiPatcher and UnityInjector.&lt;br /&gt;
&lt;br /&gt;
== Setting up ==&lt;br /&gt;
=== Installing the tools ===&lt;br /&gt;
Download and install .NET Framework, an IDE of your choice and possibly a decompiler. Follow installation instructions provided with the programs.&lt;br /&gt;
Thereafter, download and install ReiPatcher and UnityInjector according to the instructions found on their respective download pages. Verify that the patcher was installed successfully by patching UnityInjector and launching the game. '''Remember to follow all README files provided with the mods.'''&lt;br /&gt;
&lt;br /&gt;
=== Gathering required libraries ===&lt;br /&gt;
In addition to DLLs provided with ReiPatcher, we will need some additional assemblies in order to apply own plug-ins.&lt;br /&gt;
Below is the list of required DLLs and their locations:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Assembly Name !! Purpose !! Location&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Contains main patcher class || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExIni.dll&amp;lt;/code&amp;gt; || Contains classes and methods for manipulating .ini files. || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.dll&amp;lt;/code&amp;gt; || Contains tools for manipulating CIL assemblies (reading classes, methods, etc) || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Mono.Cecil.*.dll&amp;lt;/code&amp;gt; || Miscellaneous classes and tools to extend Mono.Cecil's functionality. || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ReiPatcherPlus.dll&amp;lt;/code&amp;gt; (optional) || Extends the functionality of some classes found in &amp;lt;code&amp;gt;ReiPatcher.exe&amp;lt;/code&amp;gt; || Game's main directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt; || Contains game's logic and scripts || &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt; (Either x86 or x64 will suffice)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityEngine.dll&amp;lt;/code&amp;gt; || Contains Unity Engine's wrapper classes for .NET || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;UnityInjector.dll&amp;lt;/code&amp;gt; || Contains classes for writing and loading plug-ins || &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2x86_Data\Managed&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Miscellaneous Assemblies || Additional libraries to inject into or to use || Most likely &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Copy the above-mentioned assemblies into a single folder. It will be used later in the tutorial.&lt;br /&gt;
&lt;br /&gt;
=== Creating the projects ===&lt;br /&gt;
Create an empty project in the IDE of your choice. We are going to call it &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;. When creating the project, we'll set solution name to &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;. Thereafter, we'll create two other empty projects: &amp;lt;code&amp;gt;CM3D2.HelloWorld.Patcher&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CM3D2.HelloWorld.Plugin&amp;lt;/code&amp;gt;.&lt;br /&gt;
Having done that, set solution's active configuration to &amp;quot;Release&amp;quot; and platform to &amp;quot;Any CPU&amp;quot;. Finally, set .NET Framework version to 3.5 if you haven't done so when creating the solution. &lt;br /&gt;
&lt;br /&gt;
If you are unsure of how to perform such a task, refer to the IDE's own help pages. In Visual Studio 2013, the aforementioned can be done as follows:&lt;br /&gt;
# Open Visual Studio. Click &amp;lt;code&amp;gt;File-&amp;gt;New-&amp;gt;Project&amp;lt;/code&amp;gt; (or press &amp;lt;code&amp;gt;Ctrl+Shift+N&amp;lt;/code&amp;gt;).&lt;br /&gt;
# From templates, choose &amp;lt;code&amp;gt;Visual C#-&amp;gt;Class Library&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Visual C#-&amp;gt;Windows Desktop-&amp;gt;Empty Project&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Above the list of project templates change .NET Framework version to 3.5 if it isn't already.&lt;br /&gt;
# Give a name to your project in the &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt; field. In the case of this tutorial it shall be &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Give a name to your solution name in the &amp;lt;code&amp;gt;Solution name&amp;lt;/code&amp;gt; field. In our case it is &amp;lt;code&amp;gt;CM3D2.HelloWorld&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change location of the solution if needed.&lt;br /&gt;
# Make sure &amp;lt;code&amp;gt;Create directory for solution&amp;lt;/code&amp;gt; is checked. Click &amp;quot;OK&amp;quot; and wait for solution to load up.&lt;br /&gt;
# In Solution Explorer, right click on solution's name and go &amp;lt;code&amp;gt;Properties-&amp;gt;Configuration Properties-&amp;gt;Configuration-&amp;gt;Configuration Manager&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Change &amp;quot;Active solution configuration&amp;quot; to &amp;quot;Release&amp;quot;. Under &amp;quot;Active solution platform&amp;quot;, make sure it is &amp;quot;Any CPU&amp;quot; and click &amp;quot;OK&amp;quot;. Close Configuration Manager and click OK in solution's configuration.&lt;br /&gt;
# Right click on each project and go to &amp;lt;code&amp;gt;Properties&amp;lt;/code&amp;gt; and change &amp;lt;code&amp;gt;Output type&amp;lt;/code&amp;gt; to &amp;quot;Class Library&amp;quot;. Save the project by pressing &amp;lt;code&amp;gt;Ctrl+S&amp;lt;/code&amp;gt;. Close the tabs.&lt;br /&gt;
&lt;br /&gt;
When creating other projects, refer to the next subsection about naming and their meaning.&lt;br /&gt;
&lt;br /&gt;
==== DLL types and naming ====&lt;br /&gt;
As of this writing, ReiPatcher and UnityInjector require at most three different DLLs to be created in order to apply plug-ins. Those libraries' function can be described as follows:&lt;br /&gt;
* ''Hook'' — Used by ReiPatcher. Contains methods (hooks) which will be called by the game before running its own logic. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\CM3D2(x86/x64)_Data\Managed&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Patcher'' — Used by ReiPatcher. Contains procedures that will add hook methods into game's original methods (also called hooking in programming argot). Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\Patches&amp;lt;/code&amp;gt;&lt;br /&gt;
* ''Plugin'' — User by UnityInjector. Contains Unity script that is loaded up by UnityInjector. Ready DLLs are placed to &amp;lt;code&amp;gt;&amp;lt;Game's Main Directory&amp;gt;\UnityInjector&amp;lt;/code&amp;gt;&lt;br /&gt;
Note, that if one does not need to alter the execution of any in-game methods, only ''Plugin'' DLL is needed.&lt;br /&gt;
&lt;br /&gt;
Each library needs a project of its own to be created. Unfortunately, no naming conventions exist. Therefore, it is up to the programmer to decide how to name them. Nonetheless, most of the plug-in creators seem to name their DLLs as follows: &lt;br /&gt;
 &amp;lt;code&amp;gt;CM3D2.''PluginName''.''Type''.dll&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case ''PluginName'' is self-explanatory. ''Type'', on the other hand, refers to one of the three types of DLL.&lt;br /&gt;
'''Note:''' Some people seem to prefer to replace the ''Hook'' word with ''Core'', while others leave the type out altogether.&lt;br /&gt;
&lt;br /&gt;
=== Importing the DLLs ===&lt;br /&gt;
Remember the DLLs we gathered into a single folder? Move it in the same folder as the solution. After that return to your IDE and add those libraries to projects' references.&lt;br /&gt;
In Visual Studio it can be done as follows:&lt;br /&gt;
# In Solution Explorer, click on the small arrow left to the project name to expand it.&lt;br /&gt;
# Right click on &amp;lt;code&amp;gt;References&amp;lt;/code&amp;gt; and click &amp;lt;code&amp;gt;Add Reference...&amp;lt;/code&amp;gt;.&lt;br /&gt;
# In the newly-opened window go to &amp;lt;code&amp;gt;Browse&amp;lt;/code&amp;gt; tab and click &amp;lt;code&amp;gt;Browse...&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Choose the assemblies to import (multiple can be chosen at the same time). And click &amp;quot;OK&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Below is the table of basic set of assemblies to reference for each type of DLL:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Project type !! Assemblies to reference&lt;br /&gt;
|-&lt;br /&gt;
| Hook || Assembly-CSharp.dll, UnityEngine.dll&lt;br /&gt;
|-&lt;br /&gt;
| Patcher || Assembly-CSharp.dll, UnityEngine.dll, Mono.Cecil.dll, ReiPatcher.exe, ReiPatcherPlus.dll (if you want convenience methods)&lt;br /&gt;
|-&lt;br /&gt;
| Plugin || Assembly-CSharp.dll, UnityEngine.dll, UnityInjector.dll, ExIni.dll, Hook DLL (if using ReiPatcher to hook methods. Can be added by referencing the Hook project)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Of course, if any other assemblies are to be used, they must be referenced as well.&lt;br /&gt;
&lt;br /&gt;
== Writing the hook DLL ==&lt;br /&gt;
Firstly, we shall write the hook method. If there are not any classes (.cs files) in your hook project, create a new source code file. We shall name it &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In it we shall create a basic class which is also named &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;. The structure should be the following:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice how the the class is notated as &amp;lt;code&amp;gt;static&amp;lt;/code&amp;gt;. It is not compulsory, but is a good programming choice, as we do not intend to create an instance of &amp;lt;code&amp;gt;HelloWorldHooks&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Let us define the hook method. As we have seen the definition of &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;, we know that the button has a property &amp;lt;code&amp;gt;UIButton.isEnabled&amp;lt;/code&amp;gt;. We will want to access that property so that we will not print anything when the button is disabled.&lt;br /&gt;
To access the property, we will need to have the reference of the pressed button at our disposal. Therefore, we will create a hook method with a single parameter: reference to the &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt; object. The prototype of the method will then look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Called when the game calls UIButton.OnClick(). &lt;br /&gt;
     // The parameter contains the reference to UIButton in which UIButton.OnClick() was called.&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we shall use .NET event handlers to create a custom event to which we can then add functions to call when &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; is called.&lt;br /&gt;
Contrary to .NET Framework guidelines, we shall do it by declaring a custom delegate (event handler prototype) and an event above of &amp;lt;code&amp;gt;OnClickHook()&amp;lt;/code&amp;gt; definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
 public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
 public static void OnClickHook(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // ...&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It must be noted, however, that while this way is shorter, it is against .NET guidelines and is compact only when there are just a few events to handle. Refer to [https://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx MSDN Events tutorial] if you want to do it the .NET way.&lt;br /&gt;
&lt;br /&gt;
Finally, we can call the event handlers in our defined hook. The final structure of &amp;lt;code&amp;gt;HelloWorldHooks.cs&amp;lt;/code&amp;gt; will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace CM3D2.HelloWorld.Hook&lt;br /&gt;
 {&lt;br /&gt;
     public static class HelloWorldHooks&lt;br /&gt;
     {&lt;br /&gt;
         public delegate void ButtonClickHandler(UIButton button); // Function prototype for event handlers&lt;br /&gt;
         public static event ButtonClickHandler ButtonClicked;     // Event itself&lt;br /&gt;
 &lt;br /&gt;
         public static void OnClickHook(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             // Check if there are even handlers. If true, call them.&lt;br /&gt;
             if (ButtonClicked != null) ButtonClicked(button);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the only hook method we will need. Save the class and proceed to writing the patcher.&lt;br /&gt;
&lt;br /&gt;
== Writing the patcher DLL ==&lt;br /&gt;
As discussed in the previous sections, ReiPatcher uses an API of its own to provide an easy way for patching assemblies.&lt;br /&gt;
In our patcher project, we shall create a class &amp;lt;code&amp;gt;HelloWorldPatch&amp;lt;/code&amp;gt;. To turn the class into a patcher, inherit &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt; located in &amp;lt;code&amp;gt;ReiPatcher.Patch&amp;lt;/code&amp;gt; namespace.&lt;br /&gt;
Since the class is abstract, it requires the following members to be extended/defined:&lt;br /&gt;
* &amp;lt;code&amp;gt;string Name&amp;lt;/code&amp;gt;: A get property that specifies the name of the patch&lt;br /&gt;
* &amp;lt;code&amp;gt;string Version&amp;lt;/code&amp;gt;: A get property that specifies the version of the patch.&lt;br /&gt;
* &amp;lt;code&amp;gt;bool CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method that determines whether the patch can be applied.&lt;br /&gt;
* &amp;lt;code&amp;gt;void Patch(PatcherArguments args)&amp;lt;/code&amp;gt;: A method in which one performs the patching.&lt;br /&gt;
&lt;br /&gt;
Here is the basic structure of our patch:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus; // Extends PatchBase to simplify patching. Not required to make ReiPatcher work.&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get&lt;br /&gt;
             {&lt;br /&gt;
                 // A simple way: just gets the version of CM3D2.HelloWorld.Patcher assembly&lt;br /&gt;
                 return Assembly.GetExecutingAssembly().GetName().Version.ToString();&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Checks to determine whether this patch can be applied&lt;br /&gt;
             // Return ture if ReiPatch may proceed to patch with this class&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             // Patches the assemblies using Mono.Cecil&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, we can override two more methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt;: Called after the patch has been loaded into memory, but before it is applied. Used to request assemblies that we want to patch. Also used to load our hook DLL.&lt;br /&gt;
* &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;: Called after the patch has been applied and the patched assembly saved. Can be used to run some clean-up code.&lt;br /&gt;
&lt;br /&gt;
In our case, overriding only &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; will suffice.&lt;br /&gt;
=== Pre-patching phase ===&lt;br /&gt;
Before patching we need to ask ReiPatcher to load up the assemblies we want to patch. In our case it is &amp;lt;code&amp;gt;Assembly-CSharp.dll&amp;lt;/code&amp;gt;. Moreover, we need to load our own assembly that contains the hook method.&lt;br /&gt;
&lt;br /&gt;
Assembly request is done with &amp;lt;code&amp;gt;RPConfig.RequestAssembly(string name)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is path to the assembly to patch. If the exact path is not specified, ReiPatcher will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file.&lt;br /&gt;
The number of requests is the same as the number of assemblies we want to patch.&lt;br /&gt;
&lt;br /&gt;
Having requested the assembly, we need to load our hook assembly.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a convenient method &amp;lt;code&amp;gt;LoadAssembly(string name)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is the path of the assembly. If exact path is not specified, the method will attempt to find the assembly from the path specified in AssembliesDir attribute in patcher's INI file. &lt;br /&gt;
If the method fails to find or load the assembly, it will throw an exception.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of &amp;lt;code&amp;gt;LoadAssembly&amp;lt;/code&amp;gt; can be mimicked with Mono.Cecil as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static AssemblyDefinition LoadAssembly(string name)&lt;br /&gt;
 {&lt;br /&gt;
     string path = Path.Combine(patch.AssembliesDir, name);&lt;br /&gt;
     if (!File.Exists(path)) throw new FileNotFoundException(&amp;quot;Missing DLL: &amp;quot; + path);&lt;br /&gt;
     using (Stream s = File.OpenRead(path))&lt;br /&gt;
 	     result = AssemblyDefinition.ReadAssembly(s);&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the end, this is how our &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; method should look like:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private AssemblyDefinition hookAssembly;    // Our loaded hook assembly&lt;br /&gt;
 // ...&lt;br /&gt;
 &lt;br /&gt;
 // Below Patch(PatcherArguments args)&lt;br /&gt;
 public override void PrePatch()&lt;br /&gt;
 {&lt;br /&gt;
     //Request assemblies from ReiPatcher&lt;br /&gt;
     RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
     // Load our own assemblies (like hooks, etc.)&lt;br /&gt;
     hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook.dll&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Pre-patching checks ===&lt;br /&gt;
The &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; method override is called just about before applying the patch. If we return &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, ReiPatcher will call &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Note that &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; can be called multiple times — one time for each assembly that was requested (either by our own patch or some other one). That is why it is crucial to check that we are about to patch the right assembly. That way &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method will be called the right number of times.&lt;br /&gt;
&lt;br /&gt;
To assist checking, ReiPatcher provides &amp;lt;code&amp;gt;PatcherArguments&amp;lt;/code&amp;gt; parameter, that contains the following properties:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Assembly&amp;lt;/code&amp;gt; || Assembly that ReiPatcher is about to patch. Can be used to check whether we actually want to patch it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Location&amp;lt;/code&amp;gt; || Full path to the assembly&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FromBackup&amp;lt;/code&amp;gt; || True, if the assembly was loaded from a back-up&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;WasPatched&amp;lt;/code&amp;gt; || True, if that assembly has been patched at least once during this patch cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition to checking whether the assembly is right, we also need to check if it has already been patched by our patch.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus contains another convenience method: &amp;lt;code&amp;gt;HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The method loads all attributes from the given assembly and attempts to find a match. If there is an attribute data of which matches &amp;lt;code&amp;gt;attribute&amp;lt;/code&amp;gt;, the method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
The functionality of the method is implemented as follows:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public static bool HasAttribute(AssemblyDefinition assembly, string attribute)&lt;br /&gt;
 {&lt;br /&gt;
     return patch.GetPatchedAttributes(assembly).Any(a =&amp;gt; a.Info == attribute);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We shall define an arbitrary tag, &amp;quot;CM3D2_HELLO_WORLD&amp;quot;, that we will add as an attribute to the assembly after our patch has been successfully applied. Next time ReiPatcher is run, we check whether our tag exists in the assembly. If it does, we know that our patch has already been applied.&lt;br /&gt;
&lt;br /&gt;
That way, our definition of &amp;lt;code&amp;gt;CanPatch&amp;lt;/code&amp;gt; becomes:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Below the class definition&lt;br /&gt;
 private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     //Check that we are patching the right assembly and it doesn't have our tag&lt;br /&gt;
     return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Patching phase ===&lt;br /&gt;
Having done all the checks, it is time to finally patch the assembly, which is done in &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method.&amp;lt;br/&amp;gt;&lt;br /&gt;
All in all, injecting our &amp;lt;code&amp;gt;OnClickHook(UIButton hook)&amp;lt;/code&amp;gt; requires the following steps:&lt;br /&gt;
# Get assembly's module, which is the property &amp;lt;code&amp;gt;args.Assembly.MainModule&amp;lt;/code&amp;gt;, and use its &amp;lt;code&amp;gt;GetType(string fullName)&amp;lt;/code&amp;gt; method to acquire the type definition for &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Get hook assembly's module, which is the property &amp;lt;code&amp;gt;hookAssembly.MainModule&amp;lt;/code&amp;gt;, and acquire the type definition for &amp;lt;code&amp;gt;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;lt;/code&amp;gt; (notice the use of full name containing the namespace(s) and type name).&lt;br /&gt;
# Find the &amp;lt;code&amp;gt;MethodDefinition&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;OnClick()&amp;lt;/code&amp;gt; method using &amp;lt;code&amp;gt;UIButton&amp;lt;/code&amp;gt;'s type definition.&lt;br /&gt;
# Repeat the same process for &amp;lt;code&amp;gt;OnClickHook(UIButton button)&amp;lt;/code&amp;gt; method using acquired type definition.&lt;br /&gt;
# Using hook assembly's module and method definition, get &amp;lt;code&amp;gt;MethodReference&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;HelloWorldHooks.OnClickHook()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Using &amp;lt;code&amp;gt;UIButton.OnClick()&amp;lt;/code&amp;gt;'s method definition, get its method body and from it an instance of &amp;lt;code&amp;gt;ILProcessor&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Use the IL processor to insert &amp;lt;code&amp;gt;ldarg.0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;call [method reference to OnClickHook()]&amp;lt;/code&amp;gt; instructions before the method's original first instruction.&lt;br /&gt;
# Add our patch tag to the assembly.&lt;br /&gt;
&lt;br /&gt;
The process requires to write about a dozen of lines to complete the injection. However, why not do all that with just two lines of code?&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus provides yet another method: &amp;lt;code&amp;gt;HookMethod(TypeDefinition targetType, string targetMethod, TypeDefinition hookType, string hookMethod)&amp;lt;/code&amp;gt;.&lt;br /&gt;
This method takes the type definitions created in steps 1. and 2., and automatically hooks the function! This version of the method searches for the first methods that match the given method names and hooks them together.&lt;br /&gt;
If one wants better control of which method to hook, refer to the later sections where the capabilities of ReiPatcherPlus are exposed in greater detail.&lt;br /&gt;
&lt;br /&gt;
Everything considered, our &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method turns into:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 public override void Patch(PatcherArguments args)&lt;br /&gt;
 {&lt;br /&gt;
     // Hook UIButton.OnClick method to call CM3D2.HelloWorld.Hook.HelloWorldHooks.OnClickHook()&lt;br /&gt;
     this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;),&lt;br /&gt;
                     &amp;quot;OnClick&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &lt;br /&gt;
                     &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     // Add our tag to the assembly attribute to signify that the patch has been applied successfully&lt;br /&gt;
     SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
By combining the code from the subsections above we will get a fully working patcher! Of course, it is a simple (it does not even override &amp;lt;code&amp;gt;PostPatch()&amp;lt;/code&amp;gt;!), yet fully working class.&lt;br /&gt;
In the next section we shall briefly discuss writing plug-in DLLs for UnityInjector.&lt;br /&gt;
&lt;br /&gt;
The final source of our patcher class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System.Reflection;&lt;br /&gt;
 using Mono.Cecil;&lt;br /&gt;
 using ReiPatcher;&lt;br /&gt;
 using ReiPatcher.Patch;&lt;br /&gt;
 using ReiPatcherPlus;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Patcher&lt;br /&gt;
 {&lt;br /&gt;
     public class HelloWorldPatch : PatchBase&lt;br /&gt;
     {&lt;br /&gt;
         private const string TAG = &amp;quot;CM3D2_HELLO_WORLD&amp;quot;;&lt;br /&gt;
         private AssemblyDefinition hookAssembly;&lt;br /&gt;
 &lt;br /&gt;
         public override string Version&lt;br /&gt;
         {&lt;br /&gt;
             get { return Assembly.GetExecutingAssembly().GetName().Version.ToString();}&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override string Name&lt;br /&gt;
         {&lt;br /&gt;
             get { return &amp;quot;Hello, world! Patch for CM3D2&amp;quot;; }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override bool CanPatch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             return args.Assembly.Name.Name == &amp;quot;Assembly-CSharp&amp;quot; &amp;amp;&amp;amp; !this.HasAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void Patch(PatcherArguments args)&lt;br /&gt;
         {&lt;br /&gt;
             this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;UIButton&amp;quot;), &amp;quot;OnClick&amp;quot;,&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;CM3D2.HelloWorld.Hook.HelloWorldHooks&amp;quot;), &amp;quot;OnClickHook&amp;quot;);&lt;br /&gt;
             SetPatchedAttribute(args.Assembly, TAG);&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public override void PrePatch()&lt;br /&gt;
         {&lt;br /&gt;
             RPConfig.RequestAssembly(&amp;quot;Assembly-CSharp.dll&amp;quot;);&lt;br /&gt;
             hookAssembly = this.LoadAssembly(&amp;quot;CM3D2.HelloWorld.Hook&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Writing the plug-in DLL ==&lt;br /&gt;
Finally, by using UnityInjector one can affect game's logic and objects using Unity's own scripting API.&amp;lt;br/&amp;gt;&lt;br /&gt;
It is important to notice that although UnityInjector relies on ReiPatcher to be installed, both are completely standalone tools in plug-in development.&lt;br /&gt;
It is possible to create plug-ins that are only installed by ReiPatcher, plug-ins that act as Unity's game objects loaded on-the-fly with UnityInjector, or plug-ins that take advantage of both tools to create versatile and diverse additions into Unity Engine games.&lt;br /&gt;
&lt;br /&gt;
As mentioned, UnityInjector plug-ins are not patched into the game. Instead, they are loaded dynamically and added to the game as custom &amp;lt;code&amp;gt;MonoBehavior&amp;lt;/code&amp;gt;s.&lt;br /&gt;
In other words, UnityInjector allows to insert custom scripts into the game.&lt;br /&gt;
&lt;br /&gt;
Writing plug-ins is simple: create a custom class that extends &amp;lt;code&amp;gt;PluginBase&amp;lt;/code&amp;gt;. That is it.&lt;br /&gt;
Alternatively, one can add one or many of the following attributes to the class:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute example !! Description&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginFilter(&amp;quot;&amp;lt;executable&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || The plug-in will be loaded only when the name of the game executable is the same as &amp;lt;executable&amp;gt;. If not specified, UnityInjector will always load the plug-in.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginName(&amp;quot;&amp;lt;name&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the name of the plug-in. Useful for debugging. If not specified, the name will be that of the plug-in class.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[PluginVersion(&amp;quot;&amp;lt;version&amp;gt;&amp;quot;)]&amp;lt;/code&amp;gt; || Specifies the version of the plug-in. Useful for debugging. If not specified, the version will be set to &amp;quot;1.0&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, in our case the class will look like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 // If you use ReiPatcher to make custom hooks, remember to reference your hook assembly&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== About scripting ===&lt;br /&gt;
Unlike ReiPatcher, or any other tool discussed so far, Unity does not use C# in a conventional manner. Instead of providing method overrides, the engine simply calls the methods with certain names when an event occurs. These methods are referred to as &amp;quot;messages&amp;quot; in Unity.&lt;br /&gt;
&lt;br /&gt;
There is a foison of different messages one can use to script the behaviour of the plug-in. All of them are well documented on [http://docs.unity3d.com/ScriptReference/MonoBehaviour.html Unity's own documentation website].&lt;br /&gt;
Furthermore, UnityInjector contains &amp;lt;code&amp;gt;Message&amp;lt;/code&amp;gt; enumeration with all the scriptable message names which can be used as a quick reference while creating own plug-ins.&lt;br /&gt;
&lt;br /&gt;
All in all, it is highly advised to read [http://docs.unity3d.com/Manual/ScriptingSection.html Unity's tutorial on scripting] to fully take advantage of engine's capabilities.&lt;br /&gt;
&lt;br /&gt;
=== Manipulating INI files ===&lt;br /&gt;
ReiPatcher comes bundled with ExIni, a simple library that provides the ability to work with INI configuration files.&lt;br /&gt;
&lt;br /&gt;
In our case, we want to give the user the ability to redefine the key which toggles &amp;quot;Hello, world!&amp;quot; messages on and off.&lt;br /&gt;
&lt;br /&gt;
Fortunately, ExIni and UnityInjector will create missing configuration files and properties if they do not exist. That significantly simplifies scripting.&lt;br /&gt;
Let us simply create a method &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; that will load the key configuration or create it if there isn't one:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // In the beginning of the class&lt;br /&gt;
 private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
 private bool displayText = true; // We will alter the value of this variable with the key&lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 private void LoadConfig()&lt;br /&gt;
 {&lt;br /&gt;
     // Preferences is an instance of ExIni.IniFile that is defined in PluginBase.&lt;br /&gt;
     // If no INI file is found, UnityInjector will create a one automatically.&lt;br /&gt;
     // That is why we don't need to perform any checks.&lt;br /&gt;
     // This command will attempt to find a key &amp;quot;ToggleKey&amp;quot; in section &amp;quot;Key_Mappings&amp;quot;.&lt;br /&gt;
     // If such section/key does not exist, it will be created on-the-fly.&lt;br /&gt;
     IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
 &lt;br /&gt;
     // If no key existed or it was left empty, the value will be null&lt;br /&gt;
     if (key.Value == null)&lt;br /&gt;
     {&lt;br /&gt;
         key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
         // Note that ExIni nor UnityInjector save the configuration. Remember to do it yourself!&lt;br /&gt;
         SaveConfig();&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
             // If the key is found, we attempt to parse it into UnityEngine's KeyCode enum&lt;br /&gt;
             toggleKey = (KeyCode)Enum.Parse(typeof(KeyCode), key.Value, true);&lt;br /&gt;
         }&lt;br /&gt;
         catch (Exception)&lt;br /&gt;
         {&lt;br /&gt;
             // If we fail, set reset it to the initial value and save our work&lt;br /&gt;
             toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
             key.Value = Enum.GetName(typeof(KeyCode), toggleKey);&lt;br /&gt;
             SaveConfig();&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding the event handler ===&lt;br /&gt;
If you used ReiPatcher to create a custom hook, it is high time we added an event handler for it. In that case, remember to reference the hook assembly in the plug-in project to access the hooked event.&lt;br /&gt;
In the case of this tutorial, we shall reference &amp;quot;CM3D2.HelloWorld.Hook&amp;quot; and use the namespace.&amp;lt;br/&amp;gt;&lt;br /&gt;
After that, we create an event handler called &amp;lt;code&amp;gt;OnButtonClick(UIButton button)&amp;lt;/code&amp;gt; in our plug-in. In it, we simply check that the button is enabled (that is, clickable) and we can display the text. If all lights are green, we print our message.&lt;br /&gt;
&lt;br /&gt;
Having written our event handler, it is only left to be added to the event itself. That is done in &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method, that in Unity acts as a constructor. In fact, there are not a lot of differences between the two, one of them being that &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; guarantees that all game objects have been initialised and are accessible from this method.&amp;lt;br/&amp;gt;&lt;br /&gt;
In the &amp;lt;code&amp;gt;Awake()&amp;lt;/code&amp;gt; method we firstly call &amp;lt;code&amp;gt;LoadConfig()&amp;lt;/code&amp;gt; to load the configuration file; only thereafter we add the event handler to the event.&lt;br /&gt;
&lt;br /&gt;
In the end we have ended up with two new methods in our &amp;lt;code&amp;gt;HelloWorldPlugin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // Used instead of constructor&lt;br /&gt;
 public void Awake()&lt;br /&gt;
 {&lt;br /&gt;
     LoadConfig(); // Load the configuration&lt;br /&gt;
     HelloWorldHooks.ButtonClicked += OnButtonClick; // Add our own event handler to ButtonClicked event&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // This is our event handler. It will be called every time HelloWorldHooks.OnClickHook() will be called.&lt;br /&gt;
 private void OnButtonClick(UIButton button)&lt;br /&gt;
 {&lt;br /&gt;
     // Check that button is enabled and text displaying is not disabled&lt;br /&gt;
     if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
         Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Final steps: getting input ===&lt;br /&gt;
To finish our patch, we shall implement simple input processing. Since input is updated every tick, it makes sense to put our input checking into &amp;lt;code&amp;gt;Update()&amp;lt;/code&amp;gt; message.&lt;br /&gt;
&lt;br /&gt;
The code below speaks for itself:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // On top of the class&lt;br /&gt;
 private bool isKeyPressed = false; // Helper boolean to prevent multiple toggles&lt;br /&gt;
 &lt;br /&gt;
 //...&lt;br /&gt;
 &lt;br /&gt;
 public void Update()&lt;br /&gt;
 {&lt;br /&gt;
     if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
     {&lt;br /&gt;
         // We can still use in-game classes without hooking them.&lt;br /&gt;
         // For instance, in CM3D2 we can emit button click sounds with the command above&lt;br /&gt;
         GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         displayText = !displayText;&lt;br /&gt;
         isKeyPressed = true;&lt;br /&gt;
     }&lt;br /&gt;
     else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
         isKeyPressed = false;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
In this section we discussed how to create plug-ins for UnityInjector. As we have witnessed, the process is rather simple and just requires some knowledge of Unity scripting API.&lt;br /&gt;
&lt;br /&gt;
Here is the source code for our plug-in class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 using System;&lt;br /&gt;
 using CM3D2.HelloWorld.Hook;&lt;br /&gt;
 using ExIni;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 using UnityInjector;&lt;br /&gt;
 using UnityInjector.Attributes;&lt;br /&gt;
 &lt;br /&gt;
 namespace CM3D2.HelloWorld.Plugin&lt;br /&gt;
 {&lt;br /&gt;
     [PluginName(&amp;quot;Hello, world! Unity Plug-In&amp;quot;), PluginVersion(&amp;quot;0.0.0.1&amp;quot;)]&lt;br /&gt;
     public class HelloWorldPlugin : PluginBase&lt;br /&gt;
     {&lt;br /&gt;
         private const KeyCode TOGGLE_KEY_INITIAL = KeyCode.K;&lt;br /&gt;
 &lt;br /&gt;
         private KeyCode toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
         private bool displayText = true;&lt;br /&gt;
         private bool isKeyPressed;&lt;br /&gt;
 &lt;br /&gt;
         public void Awake()&lt;br /&gt;
         {&lt;br /&gt;
             LoadConfig();&lt;br /&gt;
             HelloWorldHooks.ButtonClicked += OnButtonClick;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         public void Update()&lt;br /&gt;
         {&lt;br /&gt;
             if (!isKeyPressed &amp;amp;&amp;amp; Input.GetKeyDown(toggleKey))&lt;br /&gt;
             {&lt;br /&gt;
                 GameMain.Instance.SoundMgr.PlaySystem(displayText ? &amp;quot;SE001.ogg&amp;quot; : &amp;quot;SE002.ogg&amp;quot;);&lt;br /&gt;
                 displayText = !displayText;&lt;br /&gt;
                 isKeyPressed = true;&lt;br /&gt;
             }&lt;br /&gt;
             else if (isKeyPressed &amp;amp;&amp;amp; Input.GetKeyUp(toggleKey))&lt;br /&gt;
                 isKeyPressed = false;&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void LoadConfig()&lt;br /&gt;
         {&lt;br /&gt;
             IniKey key = Preferences[&amp;quot;Key_Mappings&amp;quot;][&amp;quot;ToggleKey&amp;quot;];&lt;br /&gt;
             if (key.Value == null)&lt;br /&gt;
             {&lt;br /&gt;
                 key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                 SaveConfig();&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 try&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = (KeyCode) Enum.Parse(typeof (KeyCode), key.Value, true);&lt;br /&gt;
                 }&lt;br /&gt;
                 catch (Exception)&lt;br /&gt;
                 {&lt;br /&gt;
                     toggleKey = TOGGLE_KEY_INITIAL;&lt;br /&gt;
                     key.Value = Enum.GetName(typeof (KeyCode), toggleKey);&lt;br /&gt;
                     SaveConfig();&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         private void OnButtonClick(UIButton button)&lt;br /&gt;
         {&lt;br /&gt;
             if (button.isEnabled &amp;amp;&amp;amp; displayText)&lt;br /&gt;
                 Console.WriteLine(&amp;quot;Beep! Hello, world!&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ReiPatcherPlus: methods overview ==&lt;br /&gt;
The previous sections have covered all of the ReiPatcher and UnityInjector API, while ReiPatcherPlus and ExIni have been covered only briefly.&lt;br /&gt;
In the following two sections ('''Note:''' ExIni will come later) we will discuss the possibilities that ReiPatcherPlus and ExIni provide.&lt;br /&gt;
&lt;br /&gt;
This section is dedicated to ReiPatcherPlus: a ReiPatcher extension that condenses complicated Mono.Cecil code into simple-to-use methods.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus is used alongside ReiPatcher to add additional functionality to programmer's patcher class that inherits ReiPatcher's &amp;lt;code&amp;gt;PatchBase&amp;lt;/code&amp;gt;.&lt;br /&gt;
As of this writing, such functionality includes method hooking, redirecting, modifying accessibility of class members, assembly loading and attribute checking.&lt;br /&gt;
&lt;br /&gt;
=== Method hooking ===&lt;br /&gt;
Consider the following class that contains the following methods:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class GameClass&lt;br /&gt;
     {&lt;br /&gt;
         public int numberOfCarrots = 42;&lt;br /&gt;
         &lt;br /&gt;
         public void GameMethod();&lt;br /&gt;
         public void GameMethod(string s, int i, bool b);&lt;br /&gt;
         private void GameMethod(byte b);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now imagine we want to do the simplest of tasks: alter &amp;lt;code&amp;gt;GameMethod()&amp;lt;/code&amp;gt; so that it calls our own method &amp;lt;code&amp;gt;MyMethod()&amp;lt;/code&amp;gt; that is located in our own assembly in namespace &amp;lt;code&amp;gt;MyNamespace.MyClass&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In this case we can use &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;, a method that injects (hooks) a call to &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt; into &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; (hook method) before the method's own instructions. That way, before &amp;lt;code&amp;gt;GameClass.Game.GameMethod()&amp;lt;/code&amp;gt; proceeds with own logic, it will call &amp;lt;code&amp;gt;MyNamespace.MyClass.MyMethod()&amp;lt;/code&amp;gt;.&amp;lt;br/&amp;gt;&lt;br /&gt;
ReiPatcherPlus has two overrides of this method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition hookType, string hookMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void HookMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition hookType, string hookMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the arguments are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the method to be hooked. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;targetMethod&amp;lt;/code&amp;gt; || Name of the method to hook.&lt;br /&gt;
|- &lt;br /&gt;
| &amp;lt;code&amp;gt;targetParams&amp;lt;/code&amp;gt; || An array containing the &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt; of each target method's arguments in the order they are defined in the method. Used to find the exact method to hook.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookType&amp;lt;/code&amp;gt; || Type (class/struct) which contains the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hookMethod&amp;lt;/code&amp;gt; || Name of the hook method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; || If true, the hooked method will pass an instance of an object in which the method was called to the hook. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In order for &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; to succeed in hooking the method, the hook must be defined with the right arguments.&lt;br /&gt;
The type and the number of arguments needed depends on the choice of the override:&lt;br /&gt;
* If the former override is chosen, the hook must contain only one argument: object of the type that contains the hooked method. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have no arguments at all.&lt;br /&gt;
* If the latter override is chosen, the hook must contain one more argument than the method it hooks: the first is the object of the type that contains the hooked method, and the rest are the same arguments as those of the method that is to be hooked. However, if &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;, the hook must have exactly the same arguments as the method that is hooked.&lt;br /&gt;
* If the former override is chosen and the hooked method contains some arguments, they will not be passed to the hook. For that, use the latter override.&lt;br /&gt;
&lt;br /&gt;
In all cases, the hook must be a method without any return values (&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is).&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
Suppose we are patching &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; assembly. Assume also that we have &amp;lt;code&amp;gt;AssemblyDefinition&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;MyNamespace&amp;lt;/code&amp;gt; assembly as a variable named &amp;lt;code&amp;gt;hookAssembly&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Therefore, we can patch the methods in patcher class's &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod()&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(Game.GameClass thatGame, string s, int i, bool b) &lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(string), typeof(int), typeof(bool) },&lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: void MyMethod(byte b)&lt;br /&gt;
 this.HookMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.GameClass&amp;quot;), &amp;quot;GameMethod&amp;quot;,&lt;br /&gt;
                 new[] { typeof(byte) }, &lt;br /&gt;
                 hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that only the ones with &amp;lt;code&amp;gt;Game.GameClass&amp;lt;/code&amp;gt; object will be able to access the &amp;lt;code&amp;gt;numberOfCarrots&amp;lt;/code&amp;gt; variable.&lt;br /&gt;
&lt;br /&gt;
=== Method redirecting ===&lt;br /&gt;
Let us consider the next class:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 namespace Game&lt;br /&gt;
 {&lt;br /&gt;
     public class Swallow&lt;br /&gt;
     {&lt;br /&gt;
         public float airSpeedVelocity = 11.2F;&lt;br /&gt;
         &lt;br /&gt;
         public float GetNeededSwallows(int coconuts);&lt;br /&gt;
         public bool IsSwallowEuropean(bool isNotAfrican);&lt;br /&gt;
         private void MakeFly(bool isUnladen, float distance);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suppose we want not to just hook a method — we want to replace it with a definition of our own! That can be achieved with ReiPatcherPlus' &amp;lt;code&amp;gt;RedirectMethod&amp;lt;/code&amp;gt; methods.&lt;br /&gt;
The overrides are akin to &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and the arguments are too:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            TypeDefinition redirectType, string redirectMethod, bool passSelf = true);&lt;br /&gt;
 &lt;br /&gt;
 void RedirectMethod(TypeDefinition targetType, string targetMethod, &lt;br /&gt;
            Type[] targetParams, TypeDefinition redirectType, string redirectMethod, &lt;br /&gt;
            bool passSelf = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The biggest difference is in how the redirect method &amp;lt;code&amp;gt;MyMethod&amp;lt;/code&amp;gt; should be defined:&lt;br /&gt;
* The return type must be &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;. If the redirect returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will return immediately without continuing the execution. If &amp;lt;code&amp;gt;false/code&amp;gt; is returned, the redirected method will proceed to its own instructions (just like in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &amp;lt;code&amp;gt;passSelf&amp;lt;/code&amp;gt; acts the same as in &amp;lt;code&amp;gt;HookMethod&amp;lt;/code&amp;gt; and therefore requires an object of the type with the redirected method (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If the redirected method has a return value (not &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;, that is), the redirect method must have an additional argument after the object type (if &amp;lt;code&amp;gt;passSelf=true&amp;lt;/code&amp;gt;): reference type of the redirected method's return value (that is an argument that has &amp;lt;code&amp;gt;out&amp;lt;/code&amp;gt; word before the type name). The value of this argument can be set by the redirect method. If redirect method returns &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, the redirected method will use that value as its own return value.&lt;br /&gt;
&lt;br /&gt;
==== Examples ====&lt;br /&gt;
With the same rules as before, here is the code that is put into &amp;lt;code&amp;gt;Patch(PatcherArguments args)&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out float result)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;, &lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
 			 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, bool isUnladen, float distance)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;MakeFly&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool), typeof(float) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // MyMethod definition: bool MyMethod(Game.Swallow swallow, out float result, int coconuts)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;GetNeededSwallows&amp;quot;,&lt;br /&gt;
                     new[] { typeof(int) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(Game.Swallow swallow, out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 // MyMethod definition: bool MyMethod(out bool result, bool isNotAfrican)&lt;br /&gt;
 this.RedirectMethod(args.Assembly.MainModule.GetType(&amp;quot;Game.Swallow&amp;quot;), &amp;quot;IsSwallowEuropean&amp;quot;,&lt;br /&gt;
                     new[] { typeof(bool) },&lt;br /&gt;
                     hookAssembly.MainModule.GetType(&amp;quot;MyNamespace.MyClass&amp;quot;), &amp;quot;MyMethod&amp;quot;, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Changing accessibility ===&lt;br /&gt;
When searching through assemblies you might encounter a member or a method that is set to be private, even though you would want to access outside the class.&lt;br /&gt;
&lt;br /&gt;
ReiPatcherPlus provides a simple method to make such private types accessible:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 void ChangeAccess(TypeDefinition type, string member, bool makePublic = true, bool makeVirtual = true);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The method has the following arguments:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || Type (class/struct) that contains the member to manipulate. Can be gained from an assembly with the &amp;lt;code&amp;gt;AssemblyDefinition.MainModule.GetType(string typeName)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; || Name of the member to manipulate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makePublic&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, will make the member public. '''Default:''' true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;makeVirtual&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;member&amp;lt;/code&amp;gt; is a method, will make it virtual. '''Default:''' true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous methods ===&lt;br /&gt;
Here are some other small methods that simplify the workflow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bool HasAttribute(AssemblyDefinition assembly, string attribute)&amp;lt;/code&amp;gt; || Checks whether the assembly has a string attribute set. Can be used in &amp;lt;code&amp;gt;CanPatch(PatcherArguments args)&amp;lt;/code&amp;gt; to determine if the patch has already been applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AssemblyDefinition LoadAssembly(string name)&amp;lt;/code&amp;gt; || Loads a custom assembly from the &amp;lt;code&amp;gt;AssembliesDir&amp;lt;/code&amp;gt; path set by ReiPatcher. Can be used in &amp;lt;code&amp;gt;PrePatch()&amp;lt;/code&amp;gt; to load hook assemblies.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Denikson</name></author>	</entry>

	</feed>