Ver código fonte

Merge branch 'master' into feature-uname-check

Geoffrey Horsington 4 anos atrás
pai
commit
1735ef59cf

+ 6 - 6
.github/ISSUE_TEMPLATE/bug_report.md

@@ -5,21 +5,21 @@ about: Create a report to help us improve
 ---
 
 **Describe the bug**
-A clear and concise description of what the bug is.
+<!--- A clear and concise description of what the bug is. -->
 
 **To Reproduce**
-A short description of what you did for the bug to happen.
+<!--- A short description of what you did for the bug to happen. -->
 
 **Expected behavior**
-A clear and concise description of what you expected to happen.
+<!--- A clear and concise description of what you expected to happen. -->
 
 **Screenshots and logs**
-Include a console log (`output_log.txt` and/or `preloader_xxx_xxx.log`), if the error is visible there.  
-If not possible, include a screenshot of the error.
+<!--- Include a console log (`output_log.txt` and/or `preloader_xxx_xxx.log`), if the error is visible there. -->
+<!--- If not possible, include a screenshot of the error. -->
 
 **Desktop (please complete the following information):**
  - Game and game version [e.g. COM3D2 1.15]: 
  - BepInEx version [e.g. 4.0]: 
 
 **Additional context**
-Add any other context about the problem here.
+<!--- Add any other context about the problem here. -->

+ 4 - 4
.github/ISSUE_TEMPLATE/feature_request.md

@@ -5,13 +5,13 @@ about: Suggest an idea for this project
 ---
 
 **Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+<!--- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
 
 **Describe the solution you'd like**
-A clear and concise description of what you want to happen.
+<!--- A clear and concise description of what you want to happen. -->
 
 **Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
+<!--- A clear and concise description of any alternative solutions or features you've considered. -->
 
 **Additional context**
-Add any other context or screenshots about the feature request here.
+<!--- Add any other context or screenshots about the feature request here. -->

+ 28 - 0
.github/pull_request_template.md

@@ -0,0 +1,28 @@
+<!--- Provide a general summary of your changes in the Title above -->
+
+## Description
+<!--- Describe your changes in detail -->
+
+## Motivation and Context
+<!--- Why is this change required? What problem does it solve? -->
+<!--- If it fixes an open issue, please link to the issue here. -->
+
+## How Has This Been Tested?
+<!--- Please describe in detail how you tested your changes. -->
+<!--- Include details of your testing environment, tests ran to see how -->
+<!--- your change affects other areas of the code, etc. -->
+
+## Screenshots (if appropriate):
+
+## Types of changes
+<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
+- [ ] Bug fix (non-breaking change which fixes an issue)
+- [ ] New feature (non-breaking change which adds functionality)
+- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
+
+## Checklist:
+<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
+<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
+- [ ] My code follows the code style of this project.
+- [ ] My change requires a change to the documentation.
+- [ ] I have updated the documentation accordingly.

+ 5 - 5
BepInEx.Preloader/BepInEx.Preloader.csproj

@@ -23,8 +23,8 @@
     <DocumentationFile>..\bin\BepInEx.Preloader.xml</DocumentationFile>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="0Harmony, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null">
-      <HintPath>..\packages\HarmonyX.2.0.6\lib\net35\0Harmony.dll</HintPath>
+    <Reference Include="0Harmony, Version=2.1.0.0, Culture=neutral, PublicKeyToken=null">
+      <HintPath>$(SolutionDir)\packages\HarmonyX.2.1.0-beta.7\lib\net35\0Harmony.dll</HintPath>
       <Private>True</Private>
     </Reference>
     <Reference Include="Mono.Cecil, Version=0.10.4.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">
@@ -69,9 +69,9 @@
       <Project>{4ffba620-f5ed-47f9-b90c-dad1316fd9b9}</Project>
       <Name>BepInEx</Name>
     </ProjectReference>
-    <ProjectReference Include="..\submodules\BepInEx.Harmony\BepInEx.Harmony\BepInEx.Harmony.csproj">
-      <Project>{54161cfe-ff42-4dde-b161-3a49545db5cd}</Project>
-      <Name>BepInEx.Harmony</Name>
+    <ProjectReference Include="..\submodules\BepInEx.Harmony\HarmonyXInterop\HarmonyXInterop.csproj">
+      <Project>{160f7fe0-288d-435c-9e7e-497d3e0de3a6}</Project>
+      <Name>HarmonyXInterop</Name>
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>

+ 59 - 6
BepInEx.Preloader/Entrypoint.cs

@@ -3,11 +3,52 @@ using System.IO;
 using System.Linq;
 using System.Reflection;
 using BepInEx.Preloader.RuntimeFixes;
+using HarmonyXInterop;
 
 namespace BepInEx.Preloader
 {
 	internal static class PreloaderRunner
 	{
+		// This is a list of important assemblies in BepInEx core folder that should be force-loaded
+		// Some games can ship these assemblies in Managed folder, in which case assembly resolving bypasses our LocalResolve
+		// On the other hand, renaming these assemblies is not viable because 3rd party assemblies
+		// that we don't build (e.g. MonoMod, Harmony, many plugins) depend on them
+		// As such, we load them early so that the game uses our version instead
+		// These assemblies should be known to be rarely edited and are known to be shipped as-is with Unity assets
+		private static readonly string[] CriticalAssemblies =
+		{
+			"Mono.Cecil.dll",
+			"Mono.Cecil.Mdb.dll",
+			"Mono.Cecil.Pdb.dll",
+			"Mono.Cecil.Rocks.dll",
+		};
+
+		private static void LoadCriticalAssemblies()
+		{
+			foreach (string criticalAssembly in CriticalAssemblies)
+			{
+				try
+				{
+					Assembly.LoadFile(Path.Combine(Paths.BepInExAssemblyDirectory, criticalAssembly));
+				}
+				catch (Exception)
+				{
+					// Suppress error for now
+					// TODO: Should we crash here if load fails? Can't use logging at this point
+				}
+			}
+		}
+
+		// Do this in a separate method to not trigger cctor prematurely
+		private static void InitializeAssemblyResolvers()
+		{
+			// Need to initialize interop first because it installs its own special assembly resolver
+			HarmonyInterop.Initialize();
+			AppDomain.CurrentDomain.AssemblyResolve += LocalResolve;
+			// Remove temporary resolver early so it won't override local resolver
+			AppDomain.CurrentDomain.AssemblyResolve -= Entrypoint.ResolveCurrentDirectory;
+		}
+
 		public static void PreloaderPreMain()
 		{
 			PlatformUtils.SetPlatform();
@@ -15,8 +56,9 @@ namespace BepInEx.Preloader
 			string bepinPath = Utility.ParentDirectory(Path.GetFullPath(EnvVars.DOORSTOP_INVOKE_DLL_PATH), 2);
 
 			Paths.SetExecutablePath(EnvVars.DOORSTOP_PROCESS_PATH, bepinPath, EnvVars.DOORSTOP_MANAGED_FOLDER_DIR);
-			AppDomain.CurrentDomain.AssemblyResolve += LocalResolve;
 
+			LoadCriticalAssemblies();
+			InitializeAssemblyResolvers();
 			PreloaderMain();
 		}
 
@@ -38,8 +80,17 @@ namespace BepInEx.Preloader
 
 			// Use parse assembly name on managed side because native GetName() can fail on some locales
 			// if the game path has "exotic" characters
-			var foundAssembly = AppDomain.CurrentDomain.GetAssemblies()
-										 .FirstOrDefault(x => Utility.TryParseAssemblyName(x.FullName, out var name) && name.Name == assemblyName.Name);
+			var validAssemblies = AppDomain.CurrentDomain
+										 .GetAssemblies()
+										 .Select(a => new { assembly = a, name = Utility.TryParseAssemblyName(a.FullName, out var name) ? name : null })
+										 .Where(a => a.name != null && a.name.Name == assemblyName.Name)
+										 .OrderByDescending(a => a.name.Version)
+										 .ToList();
+
+			// First try to match by version, then just pick the best match (generally highest)
+			// This should mainly affect cases where the game itself loads some assembly (like Mono.Cecil) 
+			var foundMatch = validAssemblies.FirstOrDefault(a => a.name.Version == assemblyName.Version) ?? validAssemblies.FirstOrDefault();
+			var foundAssembly = foundMatch?.assembly;
 
 			if (foundAssembly != null)
 				return foundAssembly;
@@ -82,16 +133,18 @@ namespace BepInEx.Preloader
 				typeof(Entrypoint).Assembly.GetType($"BepInEx.Preloader.{nameof(PreloaderRunner)}")
 								  ?.GetMethod(nameof(PreloaderRunner.PreloaderPreMain))
 								  ?.Invoke(null, null);
-
-				AppDomain.CurrentDomain.AssemblyResolve -= ResolveCurrentDirectory;
 			}
 			catch (Exception ex)
 			{
 				File.WriteAllText(silentExceptionLog, ex.ToString());
 			}
+			finally
+			{
+				AppDomain.CurrentDomain.AssemblyResolve -= ResolveCurrentDirectory;
+			}
 		}
 
-		private static Assembly ResolveCurrentDirectory(object sender, ResolveEventArgs args)
+		internal static Assembly ResolveCurrentDirectory(object sender, ResolveEventArgs args)
 		{
 			// Can't use Utils here because it's not yet resolved
 			var name = new AssemblyName(args.Name);

+ 2 - 1
BepInEx.Preloader/Patching/AssemblyPatcher.cs

@@ -148,8 +148,9 @@ namespace BepInEx.Preloader.Patching
 					}
 				}
 
+				var assName = ass.GetName();
 				Logger.Log(patcherCollection.Any() ? LogLevel.Info : LogLevel.Debug,
-					$"Loaded {patcherCollection.Count} patcher methods from {ass.GetName().FullName}");
+					$"Loaded {patcherCollection.Count} patcher method{(patcherCollection.Count == 1 ? "" : "s")} from [{assName.Name} {assName.Version}]");
 			}
 
 			foreach (KeyValuePair<string, PatcherPlugin> patcher in sortedPatchers)

+ 1 - 1
BepInEx.Preloader/Preloader.cs

@@ -84,7 +84,7 @@ namespace BepInEx.Preloader
 
 				AssemblyPatcher.AddPatchersFromDirectory(Paths.PatcherPluginPath);
 
-				Logger.LogInfo($"{AssemblyPatcher.PatcherPlugins.Count} patcher plugin(s) loaded");
+				Logger.LogInfo($"{AssemblyPatcher.PatcherPlugins.Count} patcher plugin{(AssemblyPatcher.PatcherPlugins.Count == 1 ? "" : "s")} loaded");
 
 				AssemblyPatcher.PatchAndLoad(Paths.ManagedPath);
 				AssemblyPatcher.DisposePatchers();

+ 1 - 1
BepInEx.Preloader/RuntimeFixes/TraceFix.cs

@@ -7,7 +7,7 @@ using HarmonyLib;
 namespace BepInEx.Preloader.RuntimeFixes
 {
 	/// <summary>
-	/// This exists because the Mono implementation of <see cref="Trace"/> is/was broken, and would call Write directly instead of calling TraceEvent. This class fixes that with a <see cref="BepInEx.Harmony"/> hook.
+	/// This exists because the Mono implementation of <see cref="Trace"/> is/was broken, and would call Write directly instead of calling TraceEvent.
 	/// </summary>
 	internal static class TraceFix
 	{

+ 0 - 1
BepInEx.Preloader/RuntimeFixes/UnityPatches.cs

@@ -1,7 +1,6 @@
 using System;
 using System.Collections.Generic;
 using System.Reflection;
-using BepInEx.Harmony;
 using HarmonyLib;
 
 namespace BepInEx.Preloader.RuntimeFixes

+ 1 - 1
BepInEx.Preloader/packages.config

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="HarmonyX" version="2.0.6" targetFramework="net35" />
+  <package id="HarmonyX" version="2.1.0-beta.7" targetFramework="net35" />
   <package id="Mono.Cecil" version="0.10.4" targetFramework="net35" />
   <package id="MonoMod.RuntimeDetour" version="20.11.5.1" targetFramework="net35" />
   <package id="MonoMod.Utils" version="20.11.5.1" targetFramework="net35" />

+ 14 - 0
BepInEx.sln

@@ -26,6 +26,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BepInExTests", "BepInExTest
 		{4FFBA620-F5ED-47F9-B90C-DAD1316FD9B9} = {4FFBA620-F5ED-47F9-B90C-DAD1316FD9B9}
 	EndProjectSection
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HarmonyXInterop", "submodules\BepInEx.Harmony\HarmonyXInterop\HarmonyXInterop.csproj", "{160F7FE0-288D-435C-9E7E-497D3E0DE3A6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HarmonyX2Interop", "submodules\BepInEx.Harmony\HarmonyX2Interop\HarmonyX2Interop.csproj", "{69F6541D-A0F5-419D-B0EE-F5017F1D34F3}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -55,6 +59,14 @@ Global
 		{E7CD429A-D057-48E3-8C51-E5C934E8E07B}.Debug|Any CPU.ActiveCfg = Debug|x86
 		{E7CD429A-D057-48E3-8C51-E5C934E8E07B}.Debug|Any CPU.Build.0 = Debug|x86
 		{E7CD429A-D057-48E3-8C51-E5C934E8E07B}.Release|Any CPU.ActiveCfg = Release|x86
+		{160F7FE0-288D-435C-9E7E-497D3E0DE3A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{160F7FE0-288D-435C-9E7E-497D3E0DE3A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{160F7FE0-288D-435C-9E7E-497D3E0DE3A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{160F7FE0-288D-435C-9E7E-497D3E0DE3A6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{69F6541D-A0F5-419D-B0EE-F5017F1D34F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{69F6541D-A0F5-419D-B0EE-F5017F1D34F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{69F6541D-A0F5-419D-B0EE-F5017F1D34F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{69F6541D-A0F5-419D-B0EE-F5017F1D34F3}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -63,6 +75,8 @@ Global
 		{DC89F18B-235B-4C01-AB31-AF40DCE5C4C7} = {A9071994-3533-4C1B-89DC-D817B676AB41}
 		{6E6BC1E5-5BE8-4566-B3AE-52C4CB218AEB} = {A9071994-3533-4C1B-89DC-D817B676AB41}
 		{54161CFE-FF42-4DDE-B161-3A49545DB5CD} = {BAC58F7E-AAD8-4D0C-9490-9765ACBBA6FB}
+		{160F7FE0-288D-435C-9E7E-497D3E0DE3A6} = {BAC58F7E-AAD8-4D0C-9490-9765ACBBA6FB}
+		{69F6541D-A0F5-419D-B0EE-F5017F1D34F3} = {BAC58F7E-AAD8-4D0C-9490-9765ACBBA6FB}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {55AC11EF-F568-4C79-A356-7ED9510145B1}

+ 2 - 2
BepInEx/BepInEx.csproj

@@ -41,8 +41,8 @@
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="0Harmony, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null">
-      <HintPath>..\packages\HarmonyX.2.0.6\lib\net35\0Harmony.dll</HintPath>
+    <Reference Include="0Harmony, Version=2.1.0.0, Culture=neutral, PublicKeyToken=null">
+      <HintPath>$(SolutionDir)\packages\HarmonyX.2.1.0-beta.7\lib\net35\0Harmony.dll</HintPath>
       <Private>True</Private>
     </Reference>
     <Reference Include="Mono.Cecil, Version=0.10.4.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">

+ 15 - 3
BepInEx/Bootstrap/Chainloader.cs

@@ -5,7 +5,7 @@ using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Reflection;
-using System.Text;
+using System.Runtime.CompilerServices;
 using System.Text.RegularExpressions;
 using Mono.Cecil;
 using MonoMod.Utils;
@@ -25,6 +25,18 @@ namespace BepInEx.Bootstrap
 		public static Dictionary<string, PluginInfo> PluginInfos { get; } = new Dictionary<string, PluginInfo>();
 
 		private static readonly List<BaseUnityPlugin> _plugins = new List<BaseUnityPlugin>();
+
+		// In some rare cases calling Application.unityVersion seems to cause MissingMethodException
+		// if a preloader patch applies Harmony patch to Chainloader.Initialize.
+		// The issue could be related to BepInEx being compiled against Unity 5.6 version of UnityEngine.dll,
+		// but the issue is apparently present with both official Harmony and HarmonyX
+		// We specifically prevent inlining to prevent early resolving
+		// TODO: Figure out better version obtaining mechanism (e.g. from globalmanagers)
+		private static string UnityVersion
+		{
+			[MethodImpl(MethodImplOptions.NoInlining)]
+			get => Application.unityVersion;
+		}
 		
 		/// <summary>
 		/// List of all <see cref="BepInPlugin"/> loaded via the chainloader.
@@ -99,7 +111,7 @@ namespace BepInEx.Bootstrap
 
 			if (PlatformHelper.Is(Platform.Unix))
 			{
-				Logger.LogInfo($"Detected Unity version: v{Application.unityVersion}");
+				Logger.LogInfo($"Detected Unity version: v{UnityVersion}");
 			}
 
 			Logger.LogMessage("Chainloader ready");
@@ -262,7 +274,7 @@ namespace BepInEx.Bootstrap
 				var pluginInfos = pluginsToLoad.SelectMany(p => p.Value).ToList();
 				var loadedAssemblies = new Dictionary<string, Assembly>();
 
-				Logger.LogInfo($"{pluginInfos.Count} plugins to load");
+				Logger.LogInfo($"{pluginInfos.Count} plugin{(PluginInfos.Count == 1 ? "" : "s")} to load");
 
 				// We use a sorted dictionary to ensure consistent load order
 				var dependencyDict = new SortedDictionary<string, IEnumerable<string>>(StringComparer.InvariantCultureIgnoreCase);

+ 4 - 0
BepInEx/Bootstrap/TypeLoader.cs

@@ -126,6 +126,10 @@ namespace BepInEx.Bootstrap
 					result[dll] = matches;
 					ass.Dispose();
 				}
+				catch (BadImageFormatException e)
+				{
+					Logger.LogDebug($"Skipping loading {dll} because it's not a valid .NET assembly. Full error: {e.Message}");
+				}
 				catch (Exception e)
 				{
 					Logger.LogError(e.ToString());

+ 2 - 2
BepInEx/Configuration/ConfigFile.cs

@@ -118,7 +118,7 @@ namespace BepInEx.Configuration
 						continue;
 					}
 
-					string[] split = line.Split('='); //actual config line
+					string[] split = line.Split(new [] { '=' }, 2); //actual config line
 					if (split.Length != 2)
 						continue; //empty/invalid line
 
@@ -555,4 +555,4 @@ namespace BepInEx.Configuration
 			}
 		}
 	}
-}
+}

+ 25 - 8
BepInEx/Console/Windows/WindowsConsoleDriver.cs

@@ -1,7 +1,11 @@
 using System;
 using System.IO;
+using System.Linq;
+using System.Reflection;
 using System.Text;
 using BepInEx.ConsoleUtil;
+using HarmonyLib;
+using Microsoft.Win32.SafeHandles;
 using UnityInjector.ConsoleUtil;
 
 namespace BepInEx
@@ -21,18 +25,32 @@ namespace BepInEx
 			StandardOut = Console.Out;
 		}
 
+		// Apparently on some versions of Unity (e.g. 2018.4) using old mono causes crashes on game close if
+		// IntPtr overload is used for file streams (check #139).
+		// On the other hand, not all Unity games come with SafeFileHandle overload for FileStream
+		// As such, we're trying to use SafeFileHandle when it's available and go back to IntPtr overload if not available
+		private static readonly ConstructorInfo FileStreamCtor = new[]
+		{
+			AccessTools.Constructor(typeof(FileStream), new[] { typeof(SafeFileHandle), typeof(FileAccess) }),
+			AccessTools.Constructor(typeof(FileStream), new[] { typeof(IntPtr), typeof(FileAccess) }),
+		}.FirstOrDefault(m => m != null);
+
+		private static FileStream OpenFileStream(IntPtr handle)
+		{
+			var fileHandle = new SafeFileHandle(handle, false);
+			var ctorParams = AccessTools.ActualParameters(FileStreamCtor, new object[] { fileHandle, fileHandle.DangerousGetHandle(), FileAccess.Write });
+			return (FileStream)Activator.CreateInstance(typeof(FileStream), ctorParams);
+		}
+
 		public void CreateConsole(uint codepage)
 		{
-			// On some Unity mono builds the SafeFileHandle overload for FileStream is missing
-			// so we use the older but always included one instead
-#pragma warning disable 618
 			ConsoleWindow.Attach();
 
 			// Make sure of ConsoleEncoding helper class because on some Monos
 			// Encoding.GetEncoding throws NotImplementedException on most codepages
 			// NOTE: We don't set Console.OutputEncoding because it resets any existing Console.Out writers
 			ConsoleEncoding.ConsoleCodePage = codepage;
-			
+
 			// If stdout exists, write to it, otherwise make it the same as console out
 			// Not sure if this is needed? Does the original Console.Out still work?
 			var stdout = GetOutHandle();
@@ -42,21 +60,20 @@ namespace BepInEx
 				ConsoleOut = TextWriter.Null;
 				return;
 			}
-			
-			var originalOutStream = new FileStream(stdout, FileAccess.Write);
+
+			var originalOutStream = OpenFileStream(stdout);
 			StandardOut = new StreamWriter(originalOutStream, new UTF8Encoding(false))
 			{
 				AutoFlush = true
 			};
 
-			var consoleOutStream = new FileStream(ConsoleWindow.ConsoleOutHandle, FileAccess.Write);
+			var consoleOutStream = OpenFileStream(ConsoleWindow.ConsoleOutHandle);
 			// Can't use Console.OutputEncoding because it can be null (i.e. not preference by user)
 			ConsoleOut = new StreamWriter(consoleOutStream, ConsoleEncoding.OutputEncoding)
 			{
 				AutoFlush = true
 			};
 			ConsoleActive = true;
-#pragma warning restore 618
 		}
 
 		private IntPtr GetOutHandle()

+ 1 - 1
BepInEx/Logging/HarmonyLogSource.cs

@@ -40,7 +40,7 @@ namespace BepInEx.Logging
 			HarmonyLogger.MessageReceived -= HandleHarmonyMessage;
 		}
 
-		public string SourceName { get; } = "Harmony";
+		public string SourceName { get; } = "HarmonyX";
 		public event EventHandler<LogEventArgs> LogEvent;
 	}
 }

+ 1 - 1
BepInEx/packages.config

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="HarmonyX" version="2.0.6" targetFramework="net35" />
+  <package id="HarmonyX" version="2.1.0-beta.7" targetFramework="net35" />
   <package id="Mono.Cecil" version="0.10.4" targetFramework="net35" />
   <package id="MonoMod.RuntimeDetour" version="20.11.5.1" targetFramework="net35" />
   <package id="MonoMod.Utils" version="20.11.5.1" targetFramework="net35" />

+ 1 - 1
README.md

@@ -24,7 +24,7 @@ Unity plugin framework
 ## Used libraries
 - [NeighTools/UnityDoorstop](https://github.com/NeighTools/UnityDoorstop) - 3.0.2.2 ([7fe6127](https://github.com/NeighTools/UnityDoorstop/commit/7fe6127849c6cbbb4943f3f14146ae6ade7ec0bf))
 - [NeighTools/UnityDoorstop.Unix](https://github.com/NeighTools/UnityDoorstop.Unix) - 1.3.0.0 ([a16f217](https://github.com/NeighTools/UnityDoorstop.Unix/commit/a16f21743fdadedc8e091226c6731dbf7e9113c8))
-- [BepInEx/HarmonyX](https://github.com/BepInEx/HarmonyX) - 2.0.6 ([b9fdccc](https://github.com/BepInEx/HarmonyX/commit/79056ea0da5834f78c2b6ad5bf87e95ee43a7fd1))
+- [BepInEx/HarmonyX](https://github.com/BepInEx/HarmonyX) - 2.1.0-beta.8 ([6209d73](https://github.com/BepInEx/HarmonyX/commit/6209d7393eacb1b2213f15c3c57e5e9fc60bc253))
 - [MonoMod/MonoMod](https://github.com/MonoMod/MonoMod) - v20.11.05.01 ([1775ec9](https://github.com/MonoMod/MonoMod/commit/1775ec98e76d3420b2365d6103b4f1b69761a197))
 - [jbevain/cecil](https://github.com/jbevain/cecil) - 0.10.4 ([98ec890](https://github.com/jbevain/cecil/commit/98ec890d44643ad88d573e97be0e120435eda732))
 

+ 1 - 1
submodules/BepInEx.Harmony

@@ -1 +1 @@
-Subproject commit dae82954004248028d38a43e72b42037efca0a80
+Subproject commit fa33adb597be88bb3b641b6530825eec0c7c7097