diff --git a/About/About.xml b/About/About.xml index 3fbd4b5..e6df255 100644 --- a/About/About.xml +++ b/About/About.xml @@ -2,7 +2,11 @@ MOD-E Andreas Pardeike - 1.0.0 + +
  • 1.0
  • +
  • 1.1
  • +
    + brrainz.mode If your current mod list can satisfy a loading game, this mod will ask you to reconfigure your current mod list to match the loading game automatically. After a restart, you are good to go! Installation: Put it at the TOP of the mod list. Above the Core mod. diff --git a/About/Manifest.xml b/About/Manifest.xml index 1e8ce20..dc1f633 100644 --- a/About/Manifest.xml +++ b/About/Manifest.xml @@ -1,7 +1,7 @@  net.pardeike.rimworld.mod.mod-e - 1.0.9.0 + 2.0.0.1
  • 0.19.0
  • 1.0.0
  • diff --git a/About/ModSync.xml b/About/ModSync.xml index 45c4eeb..7d00a5b 100644 --- a/About/ModSync.xml +++ b/About/ModSync.xml @@ -2,7 +2,7 @@ 4e6082da-1178-4f64-a444-9a32aab3b4f1 MOD-E - 1.0.9.0 + 2.0.0.1 False pardeike diff --git a/About/Preview.png b/About/Preview.png index d01faba..76203d0 100644 Binary files a/About/Preview.png and b/About/Preview.png differ diff --git a/LoadFolders.xml b/LoadFolders.xml new file mode 100644 index 0000000..3d1d7f3 --- /dev/null +++ b/LoadFolders.xml @@ -0,0 +1,6 @@ + + +
  • /
  • +
  • v1.1
  • +
    +
    \ No newline at end of file diff --git a/Source/CrossPromotion.cs b/Source/CrossPromotion.cs index ff6af9e..efa28cf 100644 --- a/Source/CrossPromotion.cs +++ b/Source/CrossPromotion.cs @@ -1,4 +1,4 @@ -using Harmony; +using HarmonyLib; using RimWorld; using Steamworks; using System; @@ -12,7 +12,7 @@ using Verse; using Verse.Steam; -namespace CameraPlus +namespace CrossPromotionModule { [StaticConstructorOnStartup] static class CrossPromotion @@ -28,34 +28,35 @@ static class CrossPromotion static CrossPromotion() { - var instance = HarmonyInstance.Create(_crosspromotion); - if (instance.HasAnyPatches(_crosspromotion)) + if (Harmony.HasAnyPatches(_crosspromotion)) return; - instance.Patch( - SymbolExtensions.GetMethodInfo(() => MainMenuDrawer.Init()), - postfix: new HarmonyMethod(SymbolExtensions.GetMethodInfo(() => MainMenuDrawer_Init_Postfix())) + var instance = new Harmony(_crosspromotion); + + _ = instance.Patch( + SymbolExtensions.GetMethodInfo(() => ModLister.RebuildModList()), + postfix: new HarmonyMethod(SymbolExtensions.GetMethodInfo(() => ModLister_RebuildModList_Postfix())) ); - instance.Patch( + _ = instance.Patch( AccessTools.DeclaredMethod(typeof(Page_ModsConfig), nameof(Page_ModsConfig.PostClose)), postfix: new HarmonyMethod(SymbolExtensions.GetMethodInfo(() => Page_ModsConfig_PostClose_Postfix())) ); - instance.Patch( + _ = instance.Patch( AccessTools.DeclaredMethod(typeof(WorkshopItems), "Notify_Subscribed"), postfix: new HarmonyMethod(SymbolExtensions.GetMethodInfo(() => WorkshopItems_Notify_Subscribed_Postfix(new PublishedFileId_t(0)))) ); - instance.Patch( + _ = instance.Patch( AccessTools.DeclaredMethod(typeof(Page_ModsConfig), nameof(Page_ModsConfig.DoWindowContents)), transpiler: new HarmonyMethod(SymbolExtensions.GetMethodInfo(() => Page_ModsConfig_DoWindowContents_Transpiler(null, null))) ); } - static void MainMenuDrawer_Init_Postfix() + static void ModLister_RebuildModList_Postfix() { - ModPreviewPath(0); + _ = ModPreviewPath(0); new Thread(() => { FetchPromotionMods(); }).Start(); } @@ -69,7 +70,7 @@ static void WorkshopItems_Notify_Subscribed_Postfix(PublishedFileId_t pfid) var longID = pfid.m_PublishedFileId; if (subscribingMods.Contains(longID) == false) return; - subscribingMods.Remove(longID); + _ = subscribingMods.Remove(longID); LongEventHandler.ExecuteWhenFinished(() => { @@ -92,11 +93,11 @@ static IEnumerable Page_ModsConfig_DoWindowContents_Transpiler( var list = instructions.ToList(); var beginGroupIndicies = list .Select((instr, idx) => new Pair(idx, instr)) - .Where(pair => pair.Second.operand == m_BeginGroup) + .Where(pair => pair.Second.operand is MethodInfo mi && mi == m_BeginGroup) .Select(pair => pair.First).ToArray(); var endGroupIndicies = list .Select((instr, idx) => new Pair(idx, instr)) - .Where(pair => pair.Second.operand == m_EndGroup) + .Where(pair => pair.Second.operand is MethodInfo mi && mi == m_EndGroup) .Select(pair => pair.First).ToArray(); if (beginGroupIndicies.Length != 2 || endGroupIndicies.Length != 2) return instructions; @@ -121,7 +122,7 @@ internal static string ModPreviewPath(ulong modID) { var dir = Path.GetTempPath() + "BrrainzMods" + Path.DirectorySeparatorChar; if (Directory.Exists(dir) == false) - Directory.CreateDirectory(dir); + _ = Directory.CreateDirectory(dir); return dir + modID + "-preview.jpg"; } @@ -151,7 +152,7 @@ static void AsyncUserModsQuery(UGCQueryHandle_t query, Action.APIDispatchDelegate((result, failure) => { callback(result, failure); - SteamUGC.ReleaseQueryUGCRequest(query); + _ = SteamUGC.ReleaseQueryUGCRequest(query); }); var call = SteamUGC.SendQueryUGCRequest(query); var resultHandle = CallResult.Create(callDelegate); @@ -166,7 +167,7 @@ static void AsyncDownloadQuery(UGCHandle_t content, string path, Action { for (uint i = 0; i < result.m_unNumResultsReturned; i++) @@ -198,7 +199,7 @@ internal static void FetchPromotionMods() if (File.Exists(path)) { if (previewTextures.ContainsKey(modID)) - previewTextures.Remove(modID); + _ = previewTextures.Remove(modID); } }); } @@ -249,7 +250,7 @@ static void ContentPart(Rect mainRect, float leftColumn, ModMetaData mod, Page_M var mainModID = mod.GetPublishedFileId().m_PublishedFileId; var promoMods = CrossPromotion.promotionMods.ToArray(); var thisMod = promoMods.FirstOrDefault(m => m.m_nPublishedFileId.m_PublishedFileId == mainModID); - var isLocalFile = ModLister.AllInstalledMods.Any(meta => meta.GetPublishedFileId().m_PublishedFileId == mainModID && meta.Source == ContentSource.LocalFolder); + var isLocalFile = ModLister.AllInstalledMods.Any(meta => meta.GetPublishedFileId().m_PublishedFileId == mainModID && meta.Source == ContentSource.ModsFolder); var isSubbed = workshopMods.Contains(mainModID); if (CrossPromotion.lastPresentedMod != mainModID) @@ -274,11 +275,11 @@ static void ContentPart(Rect mainRect, float leftColumn, ModMetaData mod, Page_M var outRect = new Rect(0f, 0f, leftColumn, mainRect.height); var width = outRect.width - 20f; - var imageRect = new Rect(0f, 0f, width, width * mod.previewImage.height / mod.previewImage.width); + var imageRect = new Rect(0f, 0f, width, width * mod.PreviewImage.height / mod.PreviewImage.width); var textRect = new Rect(0f, 24f + 10f + imageRect.height, width, Text.CalcHeight(description, width)); var innerRect = new Rect(0f, 0f, width, imageRect.height + 20f + 8f + 10f + textRect.height); Widgets.BeginScrollView(outRect, ref leftScroll, innerRect, true); - GUI.DrawTexture(imageRect, mod.previewImage, ScaleMode.ScaleToFit); + GUI.DrawTexture(imageRect, mod.PreviewImage, ScaleMode.ScaleToFit); var widgetRow = new WidgetRow(imageRect.xMax, imageRect.yMax + 8f, UIDirection.LeftThenDown, width, 8f); if (isLocalFile == false) { @@ -289,8 +290,8 @@ static void ContentPart(Rect mainRect, float leftColumn, ModMetaData mod, Page_M mod.enabled = false; new Thread(() => { - AccessTools.Method(typeof(Workshop), "Unsubscribe").Invoke(null, new object[] { mod }); - AccessTools.Method(typeof(Page_ModsConfig), "Notify_SteamItemUnsubscribed").Invoke(page, new object[] { mainModID }); + _ = AccessTools.Method(typeof(Workshop), "Unsubscribe").Invoke(null, new object[] { mod }); + _ = AccessTools.Method(typeof(Page_ModsConfig), "Notify_SteamItemUnsubscribed").Invoke(page, new object[] { mainModID }); }).Start(); }, true, null)); } @@ -306,7 +307,7 @@ static void ContentPart(Rect mainRect, float leftColumn, ModMetaData mod, Page_M if (widgetRow.ButtonText("Upload", null, true, true)) Find.WindowStack.Add(Dialog_MessageBox.CreateConfirmation("ConfirmSteamWorkshopUpload".Translate(), delegate { - AccessTools.Method(typeof(Workshop), "Upload").Invoke(null, new object[] { mod }); + _ = AccessTools.Method(typeof(Workshop), "Upload").Invoke(null, new object[] { mod }); }, true, null)); } @@ -336,9 +337,9 @@ static void PromotionPart(Rect mainRect, float leftColumn, float rightColumn, Mo foreach (var promoMod in promoMods) { var myModID = promoMod.m_nPublishedFileId.m_PublishedFileId; - var isLocalFile = ModLister.AllInstalledMods.Any(meta => meta.GetPublishedFileId().m_PublishedFileId == myModID && meta.Source == ContentSource.LocalFolder); + var isLocalFile = ModLister.AllInstalledMods.Any(meta => meta.GetPublishedFileId().m_PublishedFileId == myModID && meta.Source == ContentSource.ModsFolder); var isSubbed = workshopMods.Contains(myModID); - CrossPromotion.allVoteStati.TryGetValue(myModID, out var voteStatus); + _ = CrossPromotion.allVoteStati.TryGetValue(myModID, out var voteStatus); if (height > 0) height += 10f; @@ -357,10 +358,10 @@ static void PromotionPart(Rect mainRect, float leftColumn, float rightColumn, Mo foreach (var promoMod in promoMods) { var myModID = promoMod.m_nPublishedFileId.m_PublishedFileId; - var isLocalFile = ModLister.AllInstalledMods.Any(meta => meta.GetPublishedFileId().m_PublishedFileId == myModID && meta.Source == ContentSource.LocalFolder); + var isLocalFile = ModLister.AllInstalledMods.Any(meta => meta.GetPublishedFileId().m_PublishedFileId == myModID && meta.Source == ContentSource.ModsFolder); var isSubbed = workshopMods.Contains(myModID); var isActive = activeMods.Contains(myModID); - CrossPromotion.allVoteStati.TryGetValue(myModID, out var voteStatus); + _ = CrossPromotion.allVoteStati.TryGetValue(myModID, out var voteStatus); if (firstTime == false) modRect.y += 10f; @@ -400,17 +401,17 @@ void actionButtonAction() { if (isSubbed || isLocalFile) { - var orderedMods = (IEnumerable)AccessTools.Method(typeof(Page_ModsConfig), "ModsInListOrder").Invoke(page, new object[0]); + var orderedMods = (IEnumerable)AccessTools.Method(typeof(Page_ModsConfig), "ModsInListOrder").Invoke(page, Array.Empty()); page.selectedMod = orderedMods.FirstOrDefault(meta => meta.GetPublishedFileId().m_PublishedFileId == myModID); var modsBefore = orderedMods.FirstIndexOf(m => m == page.selectedMod); if (modsBefore >= 0) - Traverse.Create(page).Field("modListScrollPosition").SetValue(new Vector2(0f, modsBefore * 26f + 4f)); + _ = Traverse.Create(page).Field("modListScrollPosition").SetValue(new Vector2(0f, modsBefore * 26f + 4f)); } else new Thread(() => { CrossPromotion.subscribingMods.Add(myModID); - SteamUGC.SubscribeItem(new PublishedFileId_t(myModID)); + _ = SteamUGC.SubscribeItem(new PublishedFileId_t(myModID)); }).Start(); } var infoWindow = new Dialog_MessageBox(description, "Close".Translate(), null, actionButton, actionButtonAction, null, false, null, null); @@ -431,7 +432,7 @@ void actionButtonAction() new Thread(() => { CrossPromotion.subscribingMods.Add(myModID); - SteamUGC.SubscribeItem(new PublishedFileId_t(myModID)); + _ = SteamUGC.SubscribeItem(new PublishedFileId_t(myModID)); }).Start(); } else if (voteStatus != null && voteStatus == false) @@ -442,7 +443,7 @@ void actionButtonAction() new Thread(() => { CrossPromotion.allVoteStati[myModID] = true; - SteamUGC.SetUserItemVote(new PublishedFileId_t(myModID), true); + _ = SteamUGC.SetUserItemVote(new PublishedFileId_t(myModID), true); }).Start(); } } diff --git a/Source/GlobalSuppressions.cs b/Source/GlobalSuppressions.cs new file mode 100644 index 0000000..fa05c00 --- /dev/null +++ b/Source/GlobalSuppressions.cs @@ -0,0 +1,6 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:ModCounter.Trigger")] diff --git a/Source/Install.bat b/Source/Install.bat index 1bebf16..41332c1 100644 --- a/Source/Install.bat +++ b/Source/Install.bat @@ -1,39 +1,59 @@ -REM ################ Mod build and install script (c) Andreas Pardeike 2018 ################ +REM ################ Mod build and install script (c) Andreas Pardeike 2020 ################ REM REM Call this script from Visual Studio's Build Events post-build event command line box: -REM "$(ProjectDir)Install.bat" $(ConfigurationName) "$(ProjectDir)" "$(ProjectName)" "About Assemblies Languages Textures" +REM "$(ProjectDir)Install.bat" $(ConfigurationName) "$(ProjectDir)" "$(ProjectName)" "About Assemblies Languages Textures v1.1" "LoadFolders.xml" REM REM The project structure should look like this: REM -REM ProjectFolder +REM Modname +REM +- .git +REM +- .vs REM +- About -REM +- Assemblies +REM | +- About.xml +REM | +- Preview.png +REM | +- PublishedFileId.txt +REM +- Assemblies <----- this is for RW1.0 + Harmony 1 REM | +- 0Harmony.dll -REM | +- 0Harmony.dll.mbd (optional for debug build) -REM | +- 0Harmony.pdb (optional for debug build) +REM | +- 0Harmony.dll.mbd +REM | +- 0Harmony.pdb REM | +- Modname.dll -REM | +- Modname.dll.mbd (optional for debug build) -REM | +- Modname.pdb (optional for debug build) +REM | +- Modname.dll.mbd +REM | +- Modname.pdb REM +- Languages +REM +- packages +REM | +- Lib.Harmony.2.x.x REM +- Source -REM | +- Modname -REM | | +- Modname.csproj -REM | | +- Modname.csproj.user -REM | | +- Install.bat -REM | | +- Install.sh +REM | +- .vs +REM | +- obj +REM | +- Debug +REM | +- Release +REM | +- Properties +REM | +- Modname.csproj +REM | +- Modname.csproj.user +REM | +- packages.config +REM | +- Install.bat <----- this script REM +- Textures +REM +- v1.1 +REM | +- Assemblies <----- this is for RW1.1 + Harmony 2 +REM | +- 0Harmony.dll +REM | +- 0Harmony.dll.mbd +REM | +- 0Harmony.pdb +REM | +- Modname.dll +REM | +- Modname.dll.mbd +REM | +- Modname.pdb REM +- .gitattributes REM +- .gitignore REM +- LICENSE +REM +- LoadFolders.xml REM +- README.md REM +- Modname.sln REM REM Also needed are the following environment variables in the system settings (example values): REM -REM MONO_EXE = C:\Program Files (x86)\Mono-4\bin\mono.exe -REM PDB2MDB_PATH = C:\Program Files (x86)\Mono-4\lib\mono\4.5\pdb2mdb.exe +REM MONO_EXE = C:\Program Files\Mono\bin\mono.exe +REM PDB2MDB_PATH = C:\Program Files\Mono\lib\mono\4.5\pdb2mdb.exe REM RIMWORLD_DIR_STEAM = C:\Program Files (x86)\Steam\steamapps\common\RimWorld -REM RIMWORLD_DIR_STANDALONE = C:\Program Files (x86)\RimWorld1722Win +REM RIMWORLD_DIR_STANDALONE = %USERPROFILE%\RimWorld1-0-2408Win64 REM RIMWORLD_MOD_DEBUG = --debugger-agent=transport=dt_socket,address=127.0.0.1:56000,server=y REM REM Finally, configure Visual Studio's Debug configuration with the rimworld exe as an external @@ -55,37 +75,36 @@ SET ZIP_EXE="C:\Program Files\7-Zip\7z.exe" SET HARMONY_PATH=%SOLUTION_DIR%Assemblies\0Harmony.dll SET MOD_DLL_PATH=%SOLUTION_DIR%Assemblies\%~3.dll -ECHO # Preprocessing - IF %1==Debug ( - IF EXIST "%HARMONY_PATH:~0,-4%.pdb" ( - ECHO "Creating mdb for %HARMONY_PATH%" - "%MONO_EXE%" "%PDB2MDB_PATH%" "%HARMONY_PATH%" + ECHO "Creating mdb at %HARMONY_PATH%" + "%MONO_EXE%" "%PDB2MDB_PATH%" "%HARMONY_PATH%" 1>NUL ) IF EXIST "%MOD_DLL_PATH:~0,-4%.pdb" ( - ECHO "Creating mdb for %MOD_DLL_PATH%" - "%MONO_EXE%" "%PDB2MDB_PATH%" "%MOD_DLL_PATH%" + ECHO "Creating mdb at %MOD_DLL_PATH%" + "%MONO_EXE%" "%PDB2MDB_PATH%" "%MOD_DLL_PATH%" 1>NUL ) ) IF %1==Release ( - IF EXIST "%HARMONY_PATH%.mdb" ( ECHO "Deleting %HARMONY_PATH%.mdb" - DEL "%HARMONY_PATH%.mdb" + DEL "%HARMONY_PATH%.mdb" 1>NUL ) IF EXIST "%MOD_DLL_PATH%.mdb" ( ECHO "Deleting %MOD_DLL_PATH%.mdb" - DEL "%MOD_DLL_PATH%.mdb" + DEL "%MOD_DLL_PATH%.mdb" 1>NUL ) ) IF EXIST "%RIMWORLD_DIR_STANDALONE%" ( ECHO "Copying to %TARGET_DEBUG_DIR%" - IF NOT EXIST "%TARGET_DEBUG_DIR%" MKDIR "%TARGET_DEBUG_DIR%" + IF NOT EXIST "%TARGET_DEBUG_DIR%" MKDIR "%TARGET_DEBUG_DIR%" 1>NUL FOR %%D IN (%~4) DO ( - XCOPY /Q /I /Y /E "%SOLUTION_DIR%%%D" "%TARGET_DEBUG_DIR%\%%D" + XCOPY /I /Y /E "%SOLUTION_DIR%%%D" "%TARGET_DEBUG_DIR%\%%D" 1>NUL + ) + FOR %%D IN (%~5) DO ( + XCOPY /Y "%SOLUTION_DIR%%%D" "%TARGET_DEBUG_DIR%\*" 1>NUL ) ) @@ -93,7 +112,10 @@ IF EXIST "%RIMWORLD_DIR_STEAM%" ( ECHO "Copying to %TARGET_DIR%" IF NOT EXIST "%TARGET_DIR%" MKDIR "%TARGET_DIR%" FOR %%D IN (%~4) DO ( - XCOPY /Q /I /Y /E "%SOLUTION_DIR%%%D" "%TARGET_DIR%\%%D" + XCOPY /I /Y /E "%SOLUTION_DIR%%%D" "%TARGET_DIR%\%%D" 1>NUL ) - %ZIP_EXE% a "%TARGET_DIR%.zip" "%TARGET_DIR%" -) + FOR %%D IN (%~5) DO ( + XCOPY /Y "%SOLUTION_DIR%%%D" "%TARGET_DIR%\*" 1>NUL + ) + %ZIP_EXE% a "%TARGET_DIR%.zip" "%TARGET_DIR%" 1>NUL +) \ No newline at end of file diff --git a/Source/MOD-E.csproj b/Source/MOD-E.csproj index 7a6773e..d679170 100644 --- a/Source/MOD-E.csproj +++ b/Source/MOD-E.csproj @@ -9,7 +9,7 @@ Properties MOD_E MOD-E - v3.5 + v4.7.2 512 @@ -21,7 +21,7 @@ false none true - ..\Assemblies\ + ..\v1.1\Assemblies\ prompt @@ -32,7 +32,7 @@ none true - ..\Assemblies\ + ..\v1.1\Assemblies\ prompt @@ -41,40 +41,65 @@ + - - - ..\packages\Lib.Harmony.1.2.0.1\lib\net35\0Harmony.dll + + ..\packages\Lib.Harmony.2.0.0.5\lib\net472\0Harmony.dll - D:\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\Assembly-CSharp.dll + ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\Assembly-CSharp.dll False - D:\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\Assembly-CSharp-firstpass.dll + ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\Assembly-CSharp-firstpass.dll False + - D:\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.dll + ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.dll + False + + + ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll + False + + + ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.ImageConversionModule.dll + False + + + ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.IMGUIModule.dll + False + + + ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.InputLegacyModule.dll + False + + + ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.TextRenderingModule.dll + False + + + ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.UnityWebRequestModule.dll + False + + + ..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\RimWorld\RimWorldWin64_Data\Managed\UnityEngine.UnityWebRequestWWWModule.dll False - - Text.xml - - - + @@ -82,10 +107,6 @@ ModBuilder -v AssemblyVersion -file "$(TargetPath)" -save "$(ProjectName)-version" ModBuilder -v XMLPut -file "$(SolutionDir)About\Manifest.xml" -xpath /Manifest/version -value "{{$(ProjectName)-version}}" ModBuilder -v XMLPut -file "$(SolutionDir)About\ModSync.xml" -xpath /ModSyncNinjaData/Version -value "{{$(ProjectName)-version}}" -"$(ProjectDir)Install.bat" $(ConfigurationName) "$(ProjectDir)" "$(ProjectName)" "About Assemblies Languages" - - - - +"$(ProjectDir)Install.bat" $(ConfigurationName) "$(ProjectDir)" "$(ProjectName)" "About Assemblies Languages v1.1" "LoadFolders.xml" \ No newline at end of file diff --git a/Source/Main.cs b/Source/Main.cs index 88d4658..f6e5f7f 100644 --- a/Source/Main.cs +++ b/Source/Main.cs @@ -1,4 +1,4 @@ -using Harmony; +using HarmonyLib; using System; using System.Collections.Generic; using System.Reflection; @@ -14,10 +14,10 @@ public class MOD_E_Main : Mod public MOD_E_Main(ModContentPack content) : base(content) { - MyOwnIdentifier = content.Identifier; + MyOwnIdentifier = content.PackageId; Settings = GetSettings(); - var harmony = HarmonyInstance.Create("net.pardeike.MOD-E"); + var harmony = new Harmony("net.pardeike.MOD-E"); harmony.PatchAll(Assembly.GetExecutingAssembly()); } @@ -36,7 +36,7 @@ public override string SettingsCategory() [HarmonyPatch("FinalizeInit")] static class Game_FinalizeInit_Patch { - static void Postfix() + public static void Postfix() { ModCounter.Trigger(); } @@ -46,16 +46,16 @@ static void Postfix() [HarmonyPatch("ModListsMatch")] static class ScribeMetaHeaderUtility_ModListsMatch_Patch { - static void Prefix(ref List a, ref List b) + public static void Prefix(ref List a, ref List b) { var a2 = new List(a); - a2.RemoveAll(modID => modID == MOD_E_Main.MyOwnIdentifier); - a2.RemoveAll(modID => MOD_E_Main.Settings.IsIgnored(modID, null)); + _ = a2.RemoveAll(modID => modID == MOD_E_Main.MyOwnIdentifier); + _ = a2.RemoveAll(modID => MOD_E_Main.Settings.IsIgnored(modID, null)); a = a2; var b2 = new List(b); - b2.RemoveAll(modID => modID == MOD_E_Main.MyOwnIdentifier); - a2.RemoveAll(modID => MOD_E_Main.Settings.IsIgnored(modID, null)); + _ = b2.RemoveAll(modID => modID == MOD_E_Main.MyOwnIdentifier); + _ = a2.RemoveAll(modID => MOD_E_Main.Settings.IsIgnored(modID, null)); b = b2; } } @@ -64,10 +64,10 @@ static void Prefix(ref List a, ref List b) [HarmonyPatch("Reset")] static class ModsConfig_Reset_Patch { - static void Postfix() + public static void Postfix() { var modIDs = Traverse.Create(typeof(ModsConfig)).Field("data").Field("activeMods").GetValue>(); - modIDs.RemoveAll(modID => modID == MOD_E_Main.MyOwnIdentifier); + _ = modIDs.RemoveAll(modID => modID == MOD_E_Main.MyOwnIdentifier); modIDs.Insert(0, MOD_E_Main.MyOwnIdentifier); ModsConfig.Save(); } @@ -77,20 +77,18 @@ static void Postfix() [HarmonyPatch("TryCreateDialogsForVersionMismatchWarnings")] static class ScribeMetaHeaderUtility_TryCreateDialogsForVersionMismatchWarnings_Patch { - static bool Prefix(Action confirmedAction, ref bool __result) + public static bool Prefix(Action confirmedAction, ref bool __result) { var versionMatch = Traverse.Create(typeof(ScribeMetaHeaderUtility)).Method("VersionsMatch").GetValue(); if (BackCompatibility.IsSaveCompatibleWith(ScribeMetaHeaderUtility.loadedGameVersion) || versionMatch) { - string loadedModsSummary; - string currentModsSummary; - if (!ScribeMetaHeaderUtility.LoadedModsMatchesActiveMods(out loadedModsSummary, out currentModsSummary)) + if (!ScribeMetaHeaderUtility.LoadedModsMatchesActiveMods(out var loadedModsSummary, out var currentModsSummary)) { var missing = ModFixer.MissingModsInfo(); if (missing.Count == 0) { - var modInfoText = "ModsMismatchWarningText".Translate(new object[] { loadedModsSummary, currentModsSummary }); + var modInfoText = "ModsMismatchWarningText".Translate(loadedModsSummary, currentModsSummary); Find.WindowStack.Add(new MismatchDialog(modInfoText, confirmedAction)); } else @@ -102,7 +100,7 @@ static bool Prefix(Action confirmedAction, ref bool __result) confirmedAction(); else { - var modInfoText = "ModsMismatchWarningText".Translate(new object[] { loadedModsSummary, currentModsSummary }); + var modInfoText = "ModsMismatchWarningText".Translate(loadedModsSummary, currentModsSummary); Find.WindowStack.Add(new MismatchDialog(modInfoText, confirmedAction)); } })); diff --git a/Source/MismatchDialog.cs b/Source/MismatchDialog.cs index 15fd74b..110920d 100644 --- a/Source/MismatchDialog.cs +++ b/Source/MismatchDialog.cs @@ -16,7 +16,6 @@ public class MismatchDialog : Window public Action defaultAction; private Vector2 scrollPosition = Vector2.zero; - private readonly float creationRealTime = -1f; public override Vector2 InitialSize => new Vector2(640f, 460f); @@ -27,7 +26,6 @@ public MismatchDialog(string text, Action defaultAction) forcePause = true; absorbInputAroundWindow = true; - creationRealTime = RealTime.LastRealTime; onlyOneOfTypeAllowed = false; } diff --git a/Source/MissingModsDialog.cs b/Source/MissingModsDialog.cs index cb773f0..4a14ca0 100644 --- a/Source/MissingModsDialog.cs +++ b/Source/MissingModsDialog.cs @@ -1,8 +1,9 @@ -using Harmony; +using HarmonyLib; using Steamworks; using System; using System.Collections.Generic; using UnityEngine; +using UnityEngine.Networking; using Verse; using Verse.Steam; @@ -10,7 +11,6 @@ namespace MOD_E { public class MissingModsDialog : Window { - private const float ModRowHeight = 35f; private const float ButtonHeight = 35f; private const float buttonCount = 3f; private const float defaultSpacing = 20f; @@ -22,7 +22,6 @@ public class MissingModsDialog : Window public string header; private Vector2 scrollPosition = Vector2.zero; - private readonly float creationRealTime = -1f; public static bool rebuildList = false; public override Vector2 InitialSize => new Vector2(640f, 460f); @@ -37,7 +36,6 @@ public MissingModsDialog(List mods, Action defaultAction) forcePause = true; absorbInputAroundWindow = true; - creationRealTime = RealTime.LastRealTime; onlyOneOfTypeAllowed = false; } @@ -50,7 +48,7 @@ private void AddButton(Rect inRect, int index, string label, Action action, bool action(); } - private void IgnoreMod(ModIdAndName mod) + private static void IgnoreMod(ModIdAndName mod) { if (MOD_E_Main.Settings.ShowIgnoreConfirmation == false) { @@ -119,8 +117,7 @@ private float AddMods(Rect contentRect, bool render, out bool hasSubscribeAll, o if (MOD_E_Main.Settings.IsIgnored(mod)) continue; - ulong steamID; - if (ulong.TryParse(mod.id, out steamID) == false) + if (ulong.TryParse(mod.id, out var steamID) == false) steamID = 0; var description = mod.name; @@ -195,7 +192,7 @@ private float AddMods(Rect contentRect, bool render, out bool hasSubscribeAll, o { if (Widgets.ButtonInvisible(rect, true)) { - var term = WWW.EscapeURL(mod.name); + var term = UnityWebRequest.EscapeURL(mod.name); var url = "https://ludeon.com/forums/index.php?action=search2&advanced=1&searchtype=1&sort=relevance|desc&brd[15]=15&brd[16]=16&search=" + term; Application.OpenURL(url); //SteamUtility.OpenUrl(url); @@ -217,7 +214,7 @@ public override void DoWindowContents(Rect inRect) { if (rebuildList) { - Traverse.Create(typeof(WorkshopItems)).Method("RebuildItemsList").GetValue(); + _ = Traverse.Create(typeof(WorkshopItems)).Method("RebuildItemsList").GetValue(); rebuildList = false; } @@ -234,15 +231,13 @@ public override void DoWindowContents(Rect inRect) Widgets.Label(new Rect(0f, verticalPos, inRect.width, height), header); verticalPos += height + defaultSpacing; - bool hasSubscribeAll, allModsResolved; - Text.Font = GameFont.Small; var outRect = new Rect(inRect.x, verticalPos, inRect.width, inRect.height - ButtonHeight - defaultSpacing - 5f - verticalPos); var width = outRect.width - 16f; var viewRect = new Rect(0f, 0f, width, 0f); - viewRect.height = AddMods(viewRect, false, out hasSubscribeAll, out allModsResolved); + viewRect.height = AddMods(viewRect, false, out var hasSubscribeAll, out var allModsResolved); Widgets.BeginScrollView(outRect, ref scrollPosition, viewRect); - AddMods(viewRect, true, out hasSubscribeAll, out allModsResolved); + _ = AddMods(viewRect, true, out hasSubscribeAll, out allModsResolved); Widgets.EndScrollView(); if (hasSubscribeAll) diff --git a/Source/ModCounter.cs b/Source/ModCounter.cs index a4c64a7..5d14ea0 100644 --- a/Source/ModCounter.cs +++ b/Source/ModCounter.cs @@ -1,25 +1,22 @@ using System; -namespace MOD_E +public static class ModCounter { - public class ModCounter - { - // a very simple and gdpr friendly mod launch counter. - // no personal information is transfered and firebase - // doesn't store the IP or any other traceable information + // a very simple and gdpr friendly mod launch counter. + // no personal information is transfered and firebase + // doesn't store the IP or any other traceable information - static readonly string baseUrl = "http://us-central1-brrainz-mod-stats.cloudfunctions.net/ping?"; - public static void Trigger() + const string baseUrl = "http://us-central1-brrainz-mod-stats.cloudfunctions.net/ping?"; + public static void Trigger() + { + try { - try - { - var uri = new Uri(baseUrl + "MOD-E"); - var client = new System.Net.WebClient(); + var uri = new Uri(baseUrl + "MOD-E"); + using (var client = new System.Net.WebClient()) client.DownloadStringAsync(uri); - } - catch (Exception) - { - } + } + catch + { } } } \ No newline at end of file diff --git a/Source/ModFixer.cs b/Source/ModFixer.cs index d20f58f..574d5ed 100644 --- a/Source/ModFixer.cs +++ b/Source/ModFixer.cs @@ -1,4 +1,4 @@ -using Harmony; +using HarmonyLib; using Steamworks; using System; using System.Collections.Generic; @@ -34,8 +34,8 @@ public void ExposeData() public static class ModFixer { - static Traverse GetModWithIdentifier = Traverse.Create(typeof(ModLister)).Method("GetModWithIdentifier", new Type[] { typeof(string) }); - public static ModMetaData GetModMetaData(string modID) { return GetModWithIdentifier.GetValue(modID); } + static readonly Traverse GetModWithIdentifier = Traverse.Create(typeof(ModLister)).Method("GetModWithIdentifier", new Type[] { typeof(string) }); + public static ModMetaData GetModMetaData(string modID) { return GetModWithIdentifier.GetValue(modID, false); } static List missingMods; @@ -104,9 +104,9 @@ public static List MissingModsInfo() public static void FixMods() { var modIDs = new List(ScribeMetaHeaderUtility.loadedModIdsList); - modIDs.RemoveAll(modID => modID == MOD_E_Main.MyOwnIdentifier); + _ = modIDs.RemoveAll(modID => modID == MOD_E_Main.MyOwnIdentifier); modIDs.Insert(0, MOD_E_Main.MyOwnIdentifier); - Traverse.Create(typeof(ModsConfig)).Field("data").Field("activeMods").SetValue(modIDs); + _ = Traverse.Create(typeof(ModsConfig)).Field("data").Field("activeMods").SetValue(modIDs); ModsConfig.Save(); GenCommandLine.Restart(); } @@ -115,7 +115,7 @@ public static void SubscribeMod(ulong steamID) { new Thread(() => { - SteamUGC.SubscribeItem(new PublishedFileId_t(steamID)); + _ = SteamUGC.SubscribeItem(new PublishedFileId_t(steamID)); MissingModsDialog.rebuildList = true; }).Start(); } @@ -129,10 +129,9 @@ public static void SubscribeAllMods() var changed = false; foreach (var mod in localMissingMods) { - ulong steamID; - if (ulong.TryParse(mod.id, out steamID)) + if (ulong.TryParse(mod.id, out var steamID)) { - SteamUGC.SubscribeItem(new PublishedFileId_t(steamID)); + _ = SteamUGC.SubscribeItem(new PublishedFileId_t(steamID)); changed = true; } } diff --git a/Source/ModSettings.cs b/Source/ModSettings.cs index 75b63ad..4b55b2b 100644 --- a/Source/ModSettings.cs +++ b/Source/ModSettings.cs @@ -25,8 +25,7 @@ public bool IsIgnored(ModIdAndName mod) { return IgnoredMods.Any(mod2 => { - ulong steamID; - if (ulong.TryParse(mod.id, out steamID) == false) + if (ulong.TryParse(mod.id, out var steamID) == false) return mod2.name == mod.name; return mod2.id == mod.id; }); @@ -59,8 +58,7 @@ public override void ExposeData() private static string GetDescription(ModIdAndName mod) { - ulong steamID; - if (ulong.TryParse(mod.id, out steamID) == false) + if (ulong.TryParse(mod.id, out var steamID) == false) steamID = 0; var description = mod.name; diff --git a/Source/MultiVersionModFix.cs b/Source/MultiVersionModFix.cs deleted file mode 100644 index 9d2f434..0000000 --- a/Source/MultiVersionModFix.cs +++ /dev/null @@ -1,81 +0,0 @@ -using Harmony; -using RimWorld; -using Steamworks; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Xml; -using Verse; -using Verse.Steam; - -[StaticConstructorOnStartup] -static class MultiVersionModFix -{ - const string _multiversionmodfix = "multiversionmodfix"; - static readonly Dictionary> cachedVersions = new Dictionary>(); - - static MultiVersionModFix() - { - var instance = HarmonyInstance.Create(_multiversionmodfix); - var aBool = false; - var m_VersionCompatible = AccessTools.Property(typeof(ModMetaData), nameof(ModMetaData.VersionCompatible)).GetGetMethod(); - var m_VersionCompatiblePostfix = SymbolExtensions.GetMethodInfo(() => VersionCompatible_Postfix(null, ref aBool)); - instance.PostfixOnce(m_VersionCompatible, m_VersionCompatiblePostfix); - var m_SetWorkshopItemDataFrom = AccessTools.Method(typeof(Workshop), "SetWorkshopItemDataFrom"); - var m_SetWorkshopItemDataFrom_Postfix = SymbolExtensions.GetMethodInfo(() => SetWorkshopItemDataFrom_Postfix(default(UGCUpdateHandle_t), null)); - instance.PostfixOnce(m_SetWorkshopItemDataFrom, m_SetWorkshopItemDataFrom_Postfix); - } - - static void PostfixOnce(this HarmonyInstance instance, MethodInfo original, MethodInfo postfix) - { - var postfixes = instance.GetPatchInfo(original)?.Postfixes; - if (postfixes == null || !postfixes.Any(patch => patch != null && patch.owner == _multiversionmodfix)) - instance.Patch(original, postfix: new HarmonyMethod(postfix)); - } - - static List GetTaggedVersions(string rootDir) - { - if (cachedVersions.TryGetValue(rootDir, out var cached)) - return cached; - try - { - var xml = new XmlDocument(); - xml.Load(rootDir + Path.DirectorySeparatorChar + "About" + Path.DirectorySeparatorChar + "Manifest.xml"); - var tags = xml.SelectNodes("/Manifest/targetVersions/li").Cast().Select(node => node.InnerText); - var result = tags - .Where(tag => VersionControl.IsWellFormattedVersionString(tag)) - .Select(tag => VersionControl.VersionFromString(tag)).ToList(); - cachedVersions[rootDir] = result; - return result; - } - catch (System.Exception) - { - cachedVersions[rootDir] = null; - return null; - } - } - - static void VersionCompatible_Postfix(ModMetaData __instance, ref bool __result) - { - var taggedVersions = GetTaggedVersions(__instance.RootDir.FullName); - if (taggedVersions.NullOrEmpty()) return; - var currentVersion = VersionControl.CurrentVersion; - __result = taggedVersions - .Any(version => - version.Major == currentVersion.Major && - version.Minor == currentVersion.Minor && - (version.Build == 0 || version.Build == currentVersion.Build)); - } - - static void SetWorkshopItemDataFrom_Postfix(UGCUpdateHandle_t updateHandle, WorkshopItemHook hook) - { - var taggedVersions = GetTaggedVersions(hook.Directory.FullName); - if (!taggedVersions.NullOrEmpty()) - { - var tags = taggedVersions.Select(version => version.Major + "." + version.Minor); - tags.Add("Mod"); - SteamUGC.SetItemTags(updateHandle, tags.Distinct().ToList()); - } - } -} \ No newline at end of file diff --git a/Source/Properties/AssemblyInfo.cs b/Source/Properties/AssemblyInfo.cs index ceb3c03..2779a4a 100644 --- a/Source/Properties/AssemblyInfo.cs +++ b/Source/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.9.0")] -[assembly: AssemblyFileVersion("1.0.9.0")] \ No newline at end of file +[assembly: AssemblyVersion("2.0.0.1")] +[assembly: AssemblyFileVersion("2.0.0.1")] \ No newline at end of file diff --git a/Source/packages.config b/Source/packages.config index edc218f..3a34556 100644 --- a/Source/packages.config +++ b/Source/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/v1.1/Assemblies/0Harmony.dll b/v1.1/Assemblies/0Harmony.dll new file mode 100644 index 0000000..0478399 Binary files /dev/null and b/v1.1/Assemblies/0Harmony.dll differ diff --git a/v1.1/Assemblies/0Harmony.xml b/v1.1/Assemblies/0Harmony.xml new file mode 100644 index 0000000..6fa1ff6 --- /dev/null +++ b/v1.1/Assemblies/0Harmony.xml @@ -0,0 +1,2434 @@ + + + + 0Harmony + + + + A factory to create delegate types + + + Default constructor + + + Creates a delegate type for a method + The method + The new delegate type + + + + A getter delegate type + Type that getter gets field/property value from + Type of the value that getter gets + The instance get getter uses + An delegate + + + + A setter delegate type + Type that setter sets field/property value for + Type of the value that setter sets + The instance the setter uses + The value the setter uses + An delegate + + + + A constructor delegate type + Type that constructor creates + An delegate + + + + A helper class for fast access to getters and setters + + + Creates an instantiation delegate + Type that constructor creates + The new instantiation delegate + + + + Creates an getter delegate for a property + Type that getter reads property from + Type of the property that gets accessed + The property + The new getter delegate + + + + Creates an getter delegate for a field + Type that getter reads field from + Type of the field that gets accessed + The field + The new getter delegate + + + + Creates an getter delegate for a field (with a list of possible field names) + Type that getter reads field/property from + Type of the field/property that gets accessed + A list of possible field names + The new getter delegate + + + + Creates an setter delegate + Type that setter assigns property value to + Type of the property that gets assigned + The property + The new setter delegate + + + + Creates an setter delegate for a field + Type that setter assigns field value to + Type of the field that gets assigned + The field + The new getter delegate + + + + A delegate to invoke a method + The instance + The method parameters + The method result + + + A helper class to invoke method with delegates + + + Creates a fast invocation handler from a method + The method to invoke + Controls if boxed value object is accessed/updated directly + The + + + The directBoxValueAccess option controls how value types passed by reference (e.g. ref int, out my_struct) are handled in the arguments array + passed to the fast invocation handler. + Since the arguments array is an object array, any value types contained within it are actually references to a boxed value object. + Like any other object, there can be other references to such boxed value objects, other than the reference within the arguments array. + For example, + + var val = 5; + var box = (object)val; + var arr = new object[] { box }; + handler(arr); // for a method with parameter signature: ref/out/in int + + + + + If directBoxValueAccess is true, the boxed value object is accessed (and potentially updated) directly when the handler is called, + such that all references to the boxed object reflect the potentially updated value. + In the above example, if the method associated with the handler updates the passed (boxed) value to 10, both box and arr[0] + now reflect the value 10. Note that the original val is not updated, since boxing always copies the value into the new boxed value object. + + + If directBoxValueAccess is false (default), the boxed value object in the arguments array is replaced with a "reboxed" value object, + such that potential updates to the value are reflected only in the arguments array. + In the above example, if the method associated with the handler updates the passed (boxed) value to 10, only arr[0] now reflects the value 10. + + + + + A low level memory helper + + + Mark method for no inlining (currently only works on Mono) + The method/constructor to change + + + Detours a method + The original method/constructor + The replacement method/constructor + An error string + + + + Writes a jump to memory + The memory address + Jump destination + An error string + + + + Gets the start of a method in memory + The method/constructor + [out] Details of the exception + The method start address + + + + special parameter names that can be used in prefix and postfix methods + + + Patch function helpers + + + Adds a prefix + The patch info + The owner (Harmony ID) + The annotation info + + + + Removes a prefix + The patch info + The owner (Harmony ID) + + + + Adds a postfix + The patch info + The owner (Harmony ID) + The annotation info + + + + Removes a postfix + The patch info + The owner (Harmony ID) + + + + Adds a transpiler + The patch info + The owner (Harmony ID) + The annotation info + + + + Removes a transpiler + The patch info + The owner (Harmony ID) + + + + Adds a finalizer + The patch info + The owner (Harmony ID) + The annotation info + + + + Removes a finalizer + The patch info + The owner (Harmony ID) + + + + Removes a patch method + The patch info + The patch method + + + + Gets sorted patch methods + The original method + Patches to sort + Use debug mode + The sorted patch methods + + + + Creates new replacement method with the latest patches and detours the original method + The original method + Information describing the patches + The newly created replacement method + + + + Creates a patch sorter + Array of patches that will be sorted + Use debugging + + + Sorts internal PatchSortingWrapper collection and caches the results. + After first run the result is provided from the cache. + The original method + The sorted patch methods + + + Checks if the sorter was created with the same patch list and as a result can be reused to + get the sorted order of the patches. + List of patches to check against + true if equal + + + Removes one unresolved dependency from the least important patch. + + + Outputs all unblocked patches from the waiting list to results list + + + Adds patch to both results list and handled patches set + Patch to add + + + Wrapper used over the Patch object to allow faster dependency access and + dependency removal in case of cyclic dependencies + + + Create patch wrapper object used for sorting + Patch to wrap + + + Determines how patches sort + The other patch + integer to define sort order (-1, 0, 1) + + + Determines whether patches are equal + The other patch + true if equal + + + Hash function + A hash code + + + Bidirectionally registers Patches as after dependencies + List of dependencies to register + + + Bidirectionally registers Patches as before dependencies + List of dependencies to register + + + Bidirectionally removes Patch from after dependencies + Patch to remove + + + Bidirectionally removes Patch from before dependencies + Patch to remove + + + Specifies the type of method + + + + This is a normal method + + + This is a getter + + + This is a setter + + + This is a constructor + + + This is a static constructor + + + Specifies the type of argument + + + + This is a normal argument + + + This is a reference argument (ref) + + + This is an out argument (out) + + + This is a pointer argument (&) + + + Specifies the type of patch + + + + Any patch + + + A prefix patch + + + A postfix patch + + + A transpiler + + + A finalizer + + + A reverse patch + + + Specifies the type of reverse patch + + + + Use the unmodified original method (directly from IL) + + + Use the original as it is right now including previous patches but excluding future ones + + + The base class for all Harmony annotations (not meant to be used directly) + + + + The common information for all attributes + + + Annotation to define your Harmony patch methods + + + + An empty annotation can be used together with TargetMethod(s) + + + + An annotation that specifies a class to patch + The declaring class/type + + + + An annotation that specifies a method, property or constructor to patch + The declaring class/type + The argument types of the method or constructor to patch + + + + An annotation that specifies a method, property or constructor to patch + The declaring class/type + The name of the method, property or constructor to patch + + + + An annotation that specifies a method, property or constructor to patch + The declaring class/type + The name of the method, property or constructor to patch + An array of argument types to target overloads + + + + An annotation that specifies a method, property or constructor to patch + The declaring class/type + The name of the method, property or constructor to patch + An array of argument types to target overloads + Array of + + + + An annotation that specifies a method, property or constructor to patch + The declaring class/type + The + + + + An annotation that specifies a method, property or constructor to patch + The declaring class/type + The + An array of argument types to target overloads + + + + An annotation that specifies a method, property or constructor to patch + The declaring class/type + The + An array of argument types to target overloads + Array of + + + + An annotation that specifies a method, property or constructor to patch + The declaring class/type + The name of the method, property or constructor to patch + The + + + + An annotation that specifies a method, property or constructor to patch + The name of the method, property or constructor to patch + + + + An annotation that specifies a method, property or constructor to patch + The name of the method, property or constructor to patch + An array of argument types to target overloads + + + + An annotation that specifies a method, property or constructor to patch + The name of the method, property or constructor to patch + An array of argument types to target overloads + An array of + + + + An annotation that specifies a method, property or constructor to patch + The name of the method, property or constructor to patch + The + + + + An annotation that specifies a method, property or constructor to patch + The + + + + An annotation that specifies a method, property or constructor to patch + The + An array of argument types to target overloads + + + + An annotation that specifies a method, property or constructor to patch + The + An array of argument types to target overloads + An array of + + + + An annotation that specifies a method, property or constructor to patch + An array of argument types to target overloads + + + + An annotation that specifies a method, property or constructor to patch + An array of argument types to target overloads + An array of + + + + Annotation to define your standin methods for reverse patching + + + + An annotation that specifies the type of reverse patching + The of the reverse patch + + + + A Harmony annotation to define that all methods in a class are to be patched + + + + A Harmony annotation + + + + A Harmony annotation to define patch priority + The priority + + + + A Harmony annotation + + + + A Harmony annotation to define that a patch comes before another patch + The array of harmony IDs of the other patches + + + + A Harmony annotation + + + A Harmony annotation to define that a patch comes after another patch + The array of harmony IDs of the other patches + + + + A Harmony annotation + + + A Harmony annotation to debug a patch (output uses to log to your Desktop) + + + + Specifies the Prepare function in a patch class + + + + Specifies the Cleanup function in a patch class + + + + Specifies the TargetMethod function in a patch class + + + + Specifies the TargetMethods function in a patch class + + + + Specifies the Prefix function in a patch class + + + + Specifies the Postfix function in a patch class + + + + Specifies the Transpiler function in a patch class + + + + Specifies the Finalizer function in a patch class + + + + A Harmony annotation + + + + The name of the original argument + + + + The index of the original argument + + + + The new name of the original argument + + + + An annotation to declare injected arguments by name + + + + An annotation to declare injected arguments by index + Zero-based index + + + + An annotation to declare injected arguments by renaming them + Name of the original argument + New name + + + + An annotation to declare injected arguments by index and renaming them + Zero-based index + New name + + + + An abstract wrapper around OpCode and their operands. Used by transpilers + + + + The opcode + + + + The operand + + + + All labels defined on this instruction + + + + All exception block boundaries defined on this instruction + + + + Creates a new CodeInstruction with a given opcode and optional operand + The opcode + The operand + + + + Create a full copy (including labels and exception blocks) of a CodeInstruction + The to copy + + + + Clones a CodeInstruction and resets its labels and exception blocks + A lightweight copy of this code instruction + + + + Clones a CodeInstruction, resets labels and exception blocks and sets its opcode + The opcode + A copy of this CodeInstruction with a new opcode + + + + Clones a CodeInstruction, resets labels and exception blocks and sets its operand + The operand + A copy of this CodeInstruction with a new operand + + + + Returns a string representation of the code instruction + A string representation of the code instruction + + + + Exception block types + + + + The beginning of an exception block + + + + The beginning of a catch block + + + + The beginning of an except filter block + + + + The beginning of a fault block + + + + The beginning of a finally block + + + + The end of an exception block + + + + An exception block + + + + Block type + + + + Catch type + + + + Creates an exception block + The + The catch type + + + + The Harmony instance is the main entry to Harmony. After creating one with an unique identifier, it is used to patch and query the current application domain + + + + The unique identifier + + + + Set to true before instantiating Harmony to debug Harmony or use an environment variable to set HARMONY_DEBUG to '1' like this: cmd /C "set HARMONY_DEBUG=1 && game.exe" + This is for full debugging. To debug only specific patches, use the attribute + + + + Creates a new Harmony instance + A unique identifier (you choose your own) + A Harmony instance + + + + Searches the current assembly for Harmony annotations and uses them to create patches + + + + Creates a empty patch processor for an original method + The original method/constructor + A new instance + + + + Creates a patch class processor from an annotated class + The class/type + A new instance + + + + Creates a reverse patcher for one of your stub methods + The original method/constructor + The stand-in stub method as + A new instance + + + + Searches an assembly for Harmony annotations and uses them to create patches + The assembly + + + + Creates patches by manually specifying the methods + The original method/constructor + An optional prefix method wrapped in a object + An optional postfix method wrapped in a object + An optional transpiler method wrapped in a object + An optional finalizer method wrapped in a object + The replacement method that was created to patch the original method + + + + Patches a foreign method onto a stub method of yours and optionally applies transpilers during the process + The original method/constructor you want to duplicate + Your stub method as that will become the original. Needs to have the correct signature (either original or whatever your transpilers generates) + An optional transpiler as method that will be applied during the process + The replacement method that was created to patch the stub method + + + + Unpatches methods + The optional Harmony ID to restrict unpatching to a specific instance + This method could be static if it wasn't for the fact that unpatching creates a new replacement method that contains your harmony ID + + + + Unpatches a method + The original method/constructor + The + The optional Harmony ID to restrict unpatching to a specific instance + + + + Unpatches a method + The original method/constructor + The patch method as method to remove + + + + Test for patches from a specific Harmony ID + The Harmony ID + True if patches for this ID exist + + + + Gets patch information for a given original method + The original method/constructor + The patch information as + + + + Gets the methods this instance has patched + An enumeration of original methods/constructors + + + + Gets all patched original methods in the appdomain + An enumeration of patched original methods/constructors + + + + Gets Harmony version for all active Harmony instances + [out] The current Harmony version + A dictionary containing assembly versions keyed by Harmony IDs + + + + Under Mono, HarmonyException wraps IL compile errors with detailed information about the failure + + + + Default serialization constructor (not implemented) + The info + The context + + + + Get a list of IL instructions in pairs of offset+code + A list of key/value pairs which represent an offset and the code at that offset + + + + Get a list of IL instructions without offsets + A list of + + + + Get the error offset of the errornous IL instruction + The offset + + + + Get the index of the errornous IL instruction + The index into the list of instructions or -1 if not found + + + + A wrapper around a method to use it as a patch (for example a Prefix) + + + + The original method + + + + Class/type declaring this patch + + + + Patch method name + + + + Optional patch + + + + Array of argument types of the patch method + + + + of the patch + + + + Install this patch before patches with these Harmony IDs + + + + Install this patch after patches with these Harmony IDs + + + + Reverse patch type, see + + + + Create debug output for this patch + + + + Default constructor + + + + Creates a patch from a given method + The original method + + + + Creates a patch from a given method + The original method + The patch + A list of harmony IDs that should come after this patch + A list of harmony IDs that should come before this patch + Set to true to generate debug output + + + + Creates a patch from a given method + The patch class/type + The patch method name + The optional argument types of the patch method (for overloaded methods) + + + + Gets the names of all internal patch info fields + A list of field names + + + + Merges annotations + The list of to merge + The merged + + + + Returns a string that represents the annotation + A string representation + + + + Annotation extensions + + + + Copies annotation information + The source + The destination + + + + Clones an annotation + The to clone + A copied + + + + Merges annotations + The master + The detail + A new, merged + + + + Gets all annotations on a class/type + The class/type + A list of all + + + + Gets merged annotations on a class/type + The class/type + The merged + + + + Gets all annotations on a method + The method/constructor + A list of + + + + Gets merged annotations on a method + The method/constructor + The merged + + + + + A mutable representation of an inline signature, similar to Mono.Cecil's CallSite. + Used by the calli instruction, can be used by transpilers + + + + + See + + + + See + + + + See + + + + The list of all parameter types or function pointer signatures received by the call site + + + + The return type or function pointer signature returned by the call site + + + + Returns a string representation of the inline signature + A string representation of the inline signature + + + + + A mutable representation of a parameter type with an attached type modifier, + similar to Mono.Cecil's OptionalModifierType / RequiredModifierType and C#'s modopt / modreq + + + + + Whether this is a modopt (optional modifier type) or a modreq (required modifier type) + + + + The modifier type attached to the parameter type + + + + The modified parameter type + + + + Returns a string representation of the modifier type + A string representation of the modifier type + + + + Patch serialization + + + + Control the binding of a serialized object to a type + Specifies the assembly name of the serialized object + Specifies the type name of the serialized object + The type of the object the formatter creates a new instance of + + + + Serializes a patch info + The + The serialized data + + + + Deserialize a patch info + The serialized data + A + + + + Compare function to sort patch priorities + The patch + Zero-based index + The priority + A standard sort integer (-1, 0, 1) + + + + Serializable patch information + + + + Prefixes as an array of + + + + Postfixes as an array of + + + + Transpilers as an array of + + + + Finalizers as an array of + + + + Default constructor + + + + Returns if any of the patches wants debugging turned on + + + + Adds a prefix + + The prefix method + An owner (Harmony ID) + The priority, see + A list of Harmony IDs for prefixes that should run after this prefix + A list of Harmony IDs for prefixes that should run before this prefix + A flag that will log the replacement method via every time this prefix is used to build the replacement, even in the future + + + + Removes prefixes + The owner of the prefix or * for any prefix + + + + Adds a postfix + The postfix method + An owner (Harmony ID) + The priority, see + A list of Harmony IDs for postfixes that should run after this postfix + A list of Harmony IDs for postfixes that should run before this postfix + A flag that will log the replacement method via every time this postfix is used to build the replacement, even in the future + + + + Removes postfixes + The owner of the postfix or * for any postfix + + + + Adds a transpiler + The transpiler method + An owner (Harmony ID) + The priority, see + A list of Harmony IDs for transpilers that should run after this transpiler + A list of Harmony IDs for transpilers that should run before this transpiler + A flag that will log the replacement method via every time this patch is used to build the replacement, even in the future + + + + Removes transpilers + The owner of the transpiler or * for any transpiler + + + + Adds a finalizer + The finalizer method + An owner (Harmony ID) + The priority, see + A list of Harmony IDs for finalizers that should run after this finalizer + A list of Harmony IDs for finalizers that should run before this finalizer + A flag that will log the replacement method via every time this patch is used to build the replacement, even in the future + + + + Removes finalizers + The owner of the finalizer or * for any finalizer + + + + Removes a patch using its method + The method of the patch to remove + + + + A serializable patch + + + + Zero-based index + + + + The owner (Harmony ID) + + + + The priority, see + + + + Keep this patch before the patches indicated in the list of Harmony IDs + + + + Keep this patch after the patches indicated in the list of Harmony IDs + + + + A flag that will log the replacement method via every time this patch is used to build the replacement, even in the future + + + + The method of the static patch method + + + + Creates a patch + The method of the patch + Zero-based index + An owner (Harmony ID) + The priority, see + A list of Harmony IDs for patches that should run after this patch + A list of Harmony IDs for patches that should run before this patch + A flag that will log the replacement method via every time this patch is used to build the replacement, even in the future + + + + Get the patch method or a DynamicMethod if original patch method is a patch factory + The original method/constructor + The method of the patch + + + + Determines whether patches are equal + The other patch + true if equal + + + + Determines how patches sort + The other patch + integer to define sort order (-1, 0, 1) + + + + Hash function + A hash code + + + + A PatchClassProcessor used to turn on a class/type into patches + + + + Creates an empty patch class processor + The Harmony instance + The class to process + + + + Applies the patches + A list of all created replacement methods or null if patch class is not annotated + + + + A group of patches + + + + A collection of prefix + + + + A collection of postfix + + + + A collection of transpiler + + + + A collection of finalizer + + + + Gets all owners (Harmony IDs) or all known patches + The patch owners + + + + Creates a group of patches + An array of prefixes as + An array of postfixes as + An array of transpileres as + An array of finalizeres as + + + + A PatchProcessor handles patches on a method/constructor + + + + Creates an empty patch processor + The Harmony instance + The original method/constructor + + + + Adds a prefix + The prefix as a + A for chaining calls + + + + Adds a prefix + The prefix method + A for chaining calls + + + + Adds a postfix + The postfix as a + A for chaining calls + + + + Adds a postfix + The postfix method + A for chaining calls + + + + Adds a transpiler + The transpiler as a + A for chaining calls + + + + Adds a transpiler + The transpiler method + A for chaining calls + + + + Adds a finalizer + The finalizer as a + A for chaining calls + + + + Adds a finalizer + The finalizer method + A for chaining calls + + + + Gets all patched original methods in the appdomain + An enumeration of patched method/constructor + + + + Applies all registered patches + The generated replacement method + + + + Unpatches patches of a given type and/or Harmony ID + The patch type + Harmony ID or * for any + A for chaining calls + + + + Unpatches a specific patch + The method of the patch + A for chaining calls + + + + Gets patch information on an original + The original method/constructor + The patch information as + + + + Gets Harmony version for all active Harmony instances + [out] The current Harmony version + A dictionary containing assembly version keyed by Harmony ID + + + + Returns the methods unmodified list of code instructions + The original method/constructor + Optionally an existing generator that will be used to create all local variables and labels contained in the result (if not specified, an internal generator is used) + A list containing all the original + + + + Returns the methods unmodified list of code instructions + The original method/constructor + A new generator that now contains all local variables and labels contained in the result + A list containing all the original + + + + A low level way to read the body of a method. Used for quick searching in methods + The original method + All instructions as opcode/operand pairs + + + + A patch priority + + + + Patch last + + + + Patch with very low priority + + + + Patch with low priority + + + + Patch with lower than normal priority + + + + Patch with normal priority + + + + Patch with higher than normal priority + + + + Patch with high priority + + + + Patch with very high priority + + + + Patch first + + + + A reverse patcher + + + + Creates a reverse patcher + The Harmony instance + The original method/constructor + Your stand-in stub method as + + + + Applies the patch + The type of patch, see + The generated replacement method + + + + A collection of commonly used transpilers + + + + A transpiler that replaces all occurrences of a given method with another one + The enumeration of to act on + Method or constructor to search for + Method or constructor to replace with + Modified enumeration of + + + + A transpiler that alters instructions that match a predicate by calling an action + The enumeration of to act on + A predicate selecting the instructions to change + An action to apply to matching instructions + Modified enumeration of + + + + A transpiler that logs a text at the beginning of the method + The instructions to act on + The log text + Modified enumeration of + + + + A helper class for reflection related functions + + + + Shortcut for to simplify the use of reflections and make it work for any access level + + + + Shortcut for to simplify the use of reflections and make it work for any access level but only within the current type + + + + Gets a type by name. Prefers a full name with namespace but falls back to the first type matching the name otherwise + The name + A type or null if not found + + + + Gets all type by name from a given assembly. This is a wrapper that respects different .NET versions + The assembly + An array of types + + + + Applies a function going up the type hierarchy and stops at the first non null result + Result type of func() + The class/type to start with + The evaluation function returning T + Returns the first non null result or default(T) when reaching the top level type object + + + + Applies a function going into inner types and stops at the first non null result + Generic type parameter + The class/type to start with + The evaluation function returning T + Returns the first non null result or null with no match + + + + Gets the reflection information for a directly declared field + The class/type where the field is defined + The name of the field + A field or null when type/name is null or when the field cannot be found + + + + Gets the reflection information for a field by searching the type and all its super types + The class/type where the field is defined + The name of the field (case sensitive) + A field or null when type/name is null or when the field cannot be found + + + + Gets the reflection information for a field + The class/type where the field is declared + The zero-based index of the field inside the class definition + A field or null when type is null or when the field cannot be found + + + + Gets the reflection information for a directly declared property + The class/type where the property is declared + The name of the property (case sensitive) + A property or null when type/name is null or when the property cannot be found + + + + Gets the reflection information for the getter method of a directly declared property + The class/type where the property is declared + The name of the property (case sensitive) + A method or null when type/name is null or when the property cannot be found + + + + Gets the reflection information for the setter method of a directly declared property + The class/type where the property is declared + The name of the property (case sensitive) + A method or null when type/name is null or when the property cannot be found + + + + Gets the reflection information for a property by searching the type and all its super types + The class/type + The name + A property or null when type/name is null or when the property cannot be found + + + + Gets the reflection information for the getter method of a property by searching the type and all its super types + The class/type + The name + A method or null when type/name is null or when the property cannot be found + + + + Gets the reflection information for the setter method of a property by searching the type and all its super types + The class/type + The name + A method or null when type/name is null or when the property cannot be found + + + + Gets the reflection information for a directly declared method + The class/type where the method is declared + The name of the method (case sensitive) + Optional parameters to target a specific overload of the method + Optional list of types that define the generic version of the method + A method or null when type/name is null or when the method cannot be found + + + + Gets the reflection information for a method by searching the type and all its super types + The class/type where the method is declared + The name of the method (case sensitive) + Optional parameters to target a specific overload of the method + Optional list of types that define the generic version of the method + A method or null when type/name is null or when the method cannot be found + + + + Gets the reflection information for a method by searching the type and all its super types + The full name like Namespace.Type1.Type2:MethodName of the type where the method is declared + Optional parameters to target a specific overload of the method + Optional list of types that define the generic version of the method + A method or null when type/name is null or when the method cannot be found + + + + Gets the names of all method that are declared in a type + The declaring class/type + A list of method names + + + + Gets the names of all method that are declared in the type of the instance + An instance of the type to search in + A list of method names + + + + Gets the names of all fields that are declared in a type + The declaring class/type + A list of field names + + + + Gets the names of all fields that are declared in the type of the instance + An instance of the type to search in + A list of field names + + + + Gets the names of all properties that are declared in a type + The declaring class/type + A list of property names + + + + Gets the names of all properties that are declared in the type of the instance + An instance of the type to search in + A list of property names + + + + Gets the type of any class member of + A member + The class/type of this member + + + + Test if a class member is actually an concrete implementation + A member + True if the member is a declared + + + + Gets the real implementation of a class member + A member + The member itself if its declared. Otherwise the member that is actually implemented in some base type + + + + Gets the reflection information for a directly declared constructor + The class/type where the constructor is declared + Optional parameters to target a specific overload of the constructor + Optional parameters to only consider static constructors + A constructor info or null when type is null or when the constructor cannot be found + + + + Gets the reflection information for a constructor by searching the type and all its super types + The class/type where the constructor is declared + Optional parameters to target a specific overload of the method + Optional parameters to only consider static constructors + A constructor info or null when type is null or when the method cannot be found + + + + Gets reflection information for all declared constructors + The class/type where the constructors are declared + Optional parameters to only consider static constructors + A list of constructor infos + + + + Gets reflection information for all declared methods + The class/type where the methods are declared + A list of methods + + + + Gets reflection information for all declared properties + The class/type where the properties are declared + A list of properties + + + + Gets reflection information for all declared fields + The class/type where the fields are declared + A list of fields + + + + Gets the return type of a method or constructor + The method/constructor + The return type + + + + Given a type, returns the first inner type matching a recursive search by name + The class/type to start searching at + The name of the inner type (case sensitive) + The inner type or null if type/name is null or if a type with that name cannot be found + + + + Given a type, returns the first inner type matching a recursive search with a predicate + The class/type to start searching at + The predicate to search with + The inner type or null if type/predicate is null or if a type with that name cannot be found + + + + Given a type, returns the first method matching a predicate + The class/type to start searching at + The predicate to search with + The method or null if type/predicate is null or if a type with that name cannot be found + + + + Given a type, returns the first constructor matching a predicate + The class/type to start searching at + The predicate to search with + The constructor info or null if type/predicate is null or if a type with that name cannot be found + + + + Given a type, returns the first property matching a predicate + The class/type to start searching at + The predicate to search with + The property or null if type/predicate is null or if a type with that name cannot be found + + + + Returns an array containing the type of each object in the given array + An array of objects + An array of types or an empty array if parameters is null (if an object is null, the type for it will be object) + + + + Creates an array of input parameters for a given method and a given set of potential inputs + The method/constructor you are planing to call + The possible input parameters in any order + An object array matching the method signature + + + + A read/writable reference to an instance field + The class the field is defined in or "object" if type cannot be accessed at compile time + The type of the field + The runtime instance to access the field (leave empty for static fields) + An readable/assignable object representing the field + + + + Creates an instance field reference + The class the field is defined in or "object" if type cannot be accessed at compile time + The type of the field + The name of the field + A read and writable field reference delegate + + + + Creates an instance field reference for a specific instance + The class the field is defined in or "object" if type cannot be accessed at compile time + The type of the field + The instance + The name of the field + An readable/assignable object representing the field + + + + Creates an instance field reference delegate + The class the field is defined in or "object" if type cannot be accessed at compile time + The type of the field + The field of the field + A read and writable delegate + + + + A read/writable reference delegate to a static field + The type of the field + An readable/assignable object representing the static field + + + + Creates a static field reference + The class the field is defined in or "object" if type cannot be accessed at compile time + The type of the field + The name of the field + An readable/assignable object representing the static field + + + + Creates a static field reference delegate + The type of the field + The field + A read and writable delegate + + + + Returns who called the current method + The calling method/constructor (excluding the caller) + + + + Throws a missing member runtime exception + The type that is involved + A list of names + + + + Gets default value for a specific type + The class/type + The default value + + + + Creates an (possibly uninitialized) instance of a given type + The class/type + The new instance + + + + Makes a deep copy of any object + The type of the instance that should be created + The original object + A copy of the original object but of type T + + + + Makes a deep copy of any object + The type of the instance that should be created + The original object + [out] The copy of the original object + Optional value transformation function (taking a field name and src/dst instances) + The optional path root to start with + + + + Makes a deep copy of any object + The original object + The type of the instance that should be created + Optional value transformation function (taking a field name and src/dst instances) + The optional path root to start with + The copy of the original object + + + + Tests if a type is a struct + The type + True if the type is a struct + + + + Tests if a type is a class + The type + True if the type is a class + + + + Tests if a type is a value type + The type + True if the type is a value type + + + + Tests if a type is an integer type + The type + True if the type represents some integer + + + + Tests if a type is a floating point type + The type + True if the type represents some floating point + + + + Tests if a type is a numerical type + The type + True if the type represents some number + + + + Tests if a type is void + The type + True if the type is void + + + + Test whether an instance is of a nullable type + Type of instance + An instance to test + True if instance is of nullable type, false if not + + + + Calculates a combined hash code for an enumeration of objects + The objects + The hash code + + + + General extensions for common cases + + + + Joins an enumeration with a value converter and a delimiter to a string + The inner type of the enumeration + The enumeration + An optional value converter (from T to string) + An optional delimiter + The values joined into a string + + + + Converts an array of types (for example methods arguments) into a human readable form + The array of types + A human readable description including brackets + + + + A full description of a type + The type + A human readable description + + + + A a full description of a method or a constructor without assembly details but with generics + The method/constructor + A human readable description + + + + A helper converting parameter infos to types + The array of parameter infos + An array of types + + + + A helper to access a value via key from a dictionary + The key type + The value type + The dictionary + The key + The value for the key or the default value (of T) if that key does not exist + + + + A helper to access a value via key from a dictionary with extra casting + The value type + The dictionary + The key + The value for the key or the default value (of T) if that key does not exist or cannot be cast to T + + + + Extensions for + + + + Shortcut for testing if the operand is equal to a non-null typed value + The + The value + True if the operand has the same type and is equal to the value + + + + Tests for any form of Ldarg* + The + The (optional) index + True if it matches one of the variations + + + + Tests for Ldarga/Ldarga_S + The + The (optional) index + True if it matches one of the variations + + + + Tests for Starg/Starg_S + The + The (optional) index + True if it matches one of the variations + + + + Tests for any form of Ldloc* + The + The optional local variable + True if it matches one of the variations + + + + Tests for any form of Stloc* + The + The optional local variable + True if it matches one of the variations + + + + Tests if the code instruction branches + The + The label if the instruction is a branch operation or if not + True if the instruction branches + + + + Tests if the code instruction calls the method/constructor + The + The method + True if the instruction calls the method or constructor + + + + Tests if the code instruction loads a constant + The + True if the instruction loads a constant + + + + Tests if the code instruction loads an integer constant + The + The integer constant + True if the instruction loads the constant + + + + Tests if the code instruction loads a floating point constant + The + The floating point constant + True if the instruction loads the constant + + + + Tests if the code instruction loads an enum constant + The + The enum + True if the instruction loads the constant + + + + Tests if the code instruction loads a field + The + The field + Set to true if the address of the field is loaded + True if the instruction loads the field + + + + Tests if the code instruction stores a field + The + The field + True if the instruction stores this field + + + + General extensions for collections + + + + A simple way to execute code for every element in a collection + The inner type of the collection + The collection + The action to execute + + + + A simple way to execute code for elements in a collection matching a condition + The inner type of the collection + The collection + The predicate + The action to execute + + + + A helper to add an item to a collection + The inner type of the collection + The collection + The item to add + The collection containing the item + + + + A helper to add an item to an array + The inner type of the collection + The array + The item to add + The array containing the item + + + + A helper to add items to an array + The inner type of the collection + The array + The items to add + The array containing the items + + + + A file log for debugging + + + + Full pathname of the log file, defaults to a file called harmony.log.txt on your Desktop + + + + The indent character. The default is tab + + + + The current indent level + + + + Changes the indentation level + The value to add to the indentation level + + + + Log a string in a buffered way. Use this method only if you are sure that FlushBuffer will be called + or else logging information is incomplete in case of a crash + The string to log + + + + Logs a list of string in a buffered way. Use this method only if you are sure that FlushBuffer will be called + or else logging information is incomplete in case of a crash + A list of strings to log (they will not be re-indented) + + + + Returns the log buffer and optionally empties it + True to empty the buffer + The buffer. + + + + Replaces the buffer with new lines + The lines to store + + + + Flushes the log buffer to disk (use in combination with LogBuffered) + + + + Log a string directly to disk. Slower method that prevents missing information in case of a crash + The string to log. + + + + Resets and deletes the log + + + + Logs some bytes as hex values + The pointer to some memory + The length of bytes to log + + + + A helper class to retrieve reflection info for non-private methods + + + + Given a lambda expression that calls a method, returns the method info + The lambda expression using the method + The method in the lambda expression + + + + Given a lambda expression that calls a method, returns the method info + The generic type + The lambda expression using the method + The method in the lambda expression + + + + Given a lambda expression that calls a method, returns the method info + The generic type + The generic result type + The lambda expression using the method + The method in the lambda expression + + + + Given a lambda expression that calls a method, returns the method info + The lambda expression using the method + The method in the lambda expression + + + + A reflection helper to read and write private elements + The result type defined by GetValue() + + + + Creates a traverse instance from an existing instance + The existing instance + + + + Gets/Sets the current value + The value to read or write + + + + A reflection helper to read and write private elements + + + + Creates a new traverse instance from a class/type + The class/type + A instance + + + + Creates a new traverse instance from a class T + The class + A instance + + + + Creates a new traverse instance from an instance + The object + A instance + + + + Creates a new traverse instance from a named type + The type name, for format see + A instance + + + + Creates a new and empty traverse instance + + + + Creates a new traverse instance from a class/type + The class/type + + + + Creates a new traverse instance from an instance + The object + + + + Gets the current value + The value + + + + Gets the current value + The type of the value + The value + + + + Invokes the current method with arguments and returns the result + The method arguments + The value returned by the method + + + + Invokes the current method with arguments and returns the result + The type of the value + The method arguments + The value returned by the method + + + + Sets a value of the current field or property + The value + The same traverse instance + + + + Gets the type of the current field or property + The type + + + + Moves the current traverse instance to a inner type + The type name + A traverse instance + + + + Moves the current traverse instance to a field + The type name + A traverse instance + + + + Moves the current traverse instance to a field + The type of the field + The type name + A traverse instance + + + + Gets all fields of the current type + A list of field names + + + + Moves the current traverse instance to a property + The type name + Optional property index + A traverse instance + + + + Moves the current traverse instance to a field + The type of the property + The type name + Optional property index + A traverse instance + + + + Gets all properties of the current type + A list of property names + + + + Moves the current traverse instance to a method + The name of the method + The arguments defining the argument types of the method overload + A traverse instance + + + + Moves the current traverse instance to a method + The name of the method + The argument types of the method + The arguments for the method + A traverse instance + + + + Gets all methods of the current type + A list of method names + + + + Checks if the current traverse instance is for a field + True if its a field + + + + Checks if the current traverse instance is for a property + True if its a property + + + + Checks if the current traverse instance is for a method + True if its a method + + + + Checks if the current traverse instance is for a type + True if its a type + + + + Iterates over all fields of the current type and executes a traverse action + Original object + The action receiving a instance for each field + + + + Iterates over all fields of the current type and executes a traverse action + Original object + Target object + The action receiving a pair of instances for each field pair + + + + Iterates over all fields of the current type and executes a traverse action + Original object + Target object + The action receiving a dot path representing the field pair and the instances + + + + Iterates over all properties of the current type and executes a traverse action + Original object + The action receiving a instance for each property + + + + Iterates over all properties of the current type and executes a traverse action + Original object + Target object + The action receiving a pair of instances for each property pair + + + + Iterates over all properties of the current type and executes a traverse action + Original object + Target object + The action receiving a dot path representing the property pair and the instances + + + + A default field action that copies fields to fields + + + + Returns a string that represents the current traverse + A string representation + + + + diff --git a/v1.1/Assemblies/MOD-E.dll b/v1.1/Assemblies/MOD-E.dll new file mode 100644 index 0000000..54551d3 Binary files /dev/null and b/v1.1/Assemblies/MOD-E.dll differ