Decompiled source of MonkeyInjectionLibrary v1.0.3

BepInEx/patchers/MonkeyInjectionLibrary.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using InjectionLibrary.Attributes;
using InjectionLibrary.Exceptions;
using InjectionLibrary.Patches;
using InjectionLibrary.Utils;
using Microsoft.CodeAnalysis;
using Mono;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using MonoMod.Utils;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("BepInEx")]
[assembly: IgnoresAccessChecksTo("Mono.Cecil")]
[assembly: IgnoresAccessChecksTo("Mono.Cecil.Mdb")]
[assembly: IgnoresAccessChecksTo("Mono.Cecil.Pdb")]
[assembly: IgnoresAccessChecksTo("Mono.Cecil.Rocks")]
[assembly: AssemblyCompany("mattymatty")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.3")]
[assembly: AssemblyInformationalVersion("1.0.3+cf0d25cc571708f756abc63e502c228d473f4737")]
[assembly: AssemblyProduct("MonkeyInjectionLibrary")]
[assembly: AssemblyTitle("MonkeyInjectionLibrary")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace InjectionLibrary
{
	public enum ErrorHandlingStrategy
	{
		Terminate,
		Ignore,
		LogWarning,
		LogError
	}
	public enum ErrorLevel
	{
		None,
		Soft,
		Hard
	}
	internal static class Preloader
	{
		private static class DevelopConfig
		{
			internal static ConfigEntry<bool> Enabled;

			internal static ConfigEntry<string> OutputPath;

			internal static ConfigEntry<string> OutputExtension;

			public static void Init()
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Expected O, but got Unknown
				ConfigFile val = new ConfigFile(Utility.CombinePaths(new string[2] { MainDir, "MonkeyInjectionLibrary.Development.cfg" }), true, Plugin);
				Enabled = val.Bind<bool>("DevelOptions", "Enabled", false, "Enable development dll output");
				OutputPath = val.Bind<string>("DevelOptions", "OutputPath", MainDir, "Folder where to write the modified dlls");
				OutputExtension = val.Bind<string>("DevelOptions", "OutputExtension", ".pdll", "Extension to use for the modified dlls\n( Do not use .dll if outputting inside the BepInEx folders )");
				PropertyInfo property = ((object)val).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
				Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(val, null);
				dictionary.Clear();
				val.Save();
			}
		}

		private static class ModConfig
		{
			internal static ConfigEntry<bool> EnhancedCompatibility;

			public static void Init()
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Expected O, but got Unknown
				ConfigFile val = new ConfigFile(Utility.CombinePaths(new string[2]
				{
					Paths.ConfigPath,
					"MonkeyInjectionLibrary.cfg"
				}), true, Plugin);
				EnhancedCompatibility = val.Bind<bool>("LoadOptions", "enhanced_compatibility", false, "Try to load missing assemblies from BepInEx folders");
				PropertyInfo property = ((object)val).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
				Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(val, null);
				dictionary.Clear();
				val.Save();
			}
		}

		public const string GUID = "mattymatty.MonkeyInjectionLibrary";

		public const string NAME = "MonkeyInjectionLibrary";

		public const string VERSION = "1.0.3";

		internal static readonly BepInPlugin Plugin = new BepInPlugin("mattymatty.MonkeyInjectionLibrary", "MonkeyInjectionLibrary", "1.0.3");

		private static ReaderParameters _readerParameters;

		private static readonly string BepInPluginAttributeName = typeof(BepInPlugin).FullName;

		private static readonly string InjectionIdentifierAttributeName = typeof(InjectionIdentifierAttribute).FullName;

		private static readonly string RequiresInjectionAttributeName = typeof(RequiresInjectionsAttribute).FullName;

		private static readonly string InjectInterfaceAttributeName = typeof(InjectInterfaceAttribute).FullName;

		private static readonly string HandleErrorsAttributeName = typeof(HandleErrorsAttribute).FullName;

		private static readonly string MainDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

		private static readonly Dictionary<string, Dictionary<string, List<(string modIdentifier, TypeDefinition @interface, ErrorHandlingStrategy strategy)>>> Interfaces = new Dictionary<string, Dictionary<string, List<(string, TypeDefinition, ErrorHandlingStrategy)>>>();

		private static readonly LinkedList<AssemblyDefinition> LoadedAssemblies = new LinkedList<AssemblyDefinition>();

		private static readonly HashSet<string> TargetTypes = new HashSet<string>();

		[CompilerGenerated]
		private static ErrorLevel <inError>k__BackingField;

		private static string _targetAssembly;

		internal static ManualLogSource Log { get; } = Logger.CreateLogSource("InjectionLibrary");

		internal static ErrorLevel inError
		{
			[CompilerGenerated]
			get
			{
				return <inError>k__BackingField;
			}
			set
			{
				if (value > <inError>k__BackingField)
				{
					<inError>k__BackingField = value;
				}
			}
		}

		public static IEnumerable<string> TargetDLLs => EnumerateTargetDlLs();

		private static IEnumerable<string> EnumerateTargetDlLs()
		{
			FindInjections();
			Log.LogInfo((object)$"Found {LoadedAssemblies.Count} assemblies that require Injections");
			foreach (string key in Interfaces.Keys)
			{
				if (inError > ErrorLevel.Soft)
				{
					break;
				}
				_targetAssembly = key;
				yield return key;
			}
			_targetAssembly = null;
		}

		public static void Patch(ref AssemblyDefinition assembly)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			if (inError > ErrorLevel.Soft)
			{
				return;
			}
			try
			{
				if (Interfaces.TryGetValue(_targetAssembly, out Dictionary<string, List<(string, TypeDefinition, ErrorHandlingStrategy)>> value))
				{
					Log.LogInfo((object)("Patching " + _targetAssembly));
					Enumerator<ModuleDefinition> enumerator = assembly.Modules.GetEnumerator();
					try
					{
						while (enumerator.MoveNext())
						{
							ModuleDefinition current = enumerator.Current;
							current.assembly_resolver = Disposable.NotOwned<IAssemblyResolver>((IAssemblyResolver)(object)TypeLoader.Resolver);
							current.metadata_resolver = (IMetadataResolver)new MetadataResolver((IAssemblyResolver)(object)TypeLoader.Resolver);
							Enumerator<TypeDefinition> enumerator2 = current.Types.GetEnumerator();
							try
							{
								while (enumerator2.MoveNext())
								{
									TypeDefinition current2 = enumerator2.Current;
									if (!value.TryGetValue(((MemberReference)current2).FullName, out var value2))
									{
										continue;
									}
									TargetTypes.Remove(((MemberReference)current2).FullName + " from " + _targetAssembly);
									foreach (var (modIdentifier, val, errorHandlingStrategy) in value2)
									{
										current2.ImplementInterface((TypeReference)(object)val, modIdentifier, errorHandlingStrategy);
									}
								}
							}
							finally
							{
								((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
							}
						}
					}
					finally
					{
						((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
					}
				}
			}
			catch (Exception ex)
			{
				inError = ErrorLevel.Hard;
				if (!(ex is TerminationException))
				{
					Log.LogFatal((object)$"Exception while patching {((AssemblyNameReference)assembly.Name).Name}:\n{ex}");
				}
			}
			if (DevelopConfig.Enabled.Value)
			{
				string text = DevelopConfig.OutputPath.Value + "/" + ((AssemblyNameReference)assembly.Name).Name + DevelopConfig.OutputExtension.Value;
				Log.LogWarning((object)("Saving modified Assembly to " + text));
				assembly.Write(text);
			}
		}

		public static void Initialize()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			Log.LogInfo((object)"Preloader Started");
			ModConfig.Init();
			DevelopConfig.Init();
			_readerParameters = new ReaderParameters
			{
				ReadWrite = false,
				ReadSymbols = false,
				ReadingMode = (ReadingMode)2,
				AssemblyResolver = (IAssemblyResolver)(object)TypeLoader.Resolver
			};
			if (!ModConfig.EnhancedCompatibility.Value)
			{
				return;
			}
			AppDomain.CurrentDomain.AssemblyResolve += delegate(object _, ResolveEventArgs args)
			{
				AssemblyName assemblyName = new AssemblyName(args.Name);
				Assembly result = default(Assembly);
				foreach (string item in new string[3]
				{
					Paths.BepInExAssemblyDirectory,
					Paths.PluginPath,
					Paths.PatcherPluginPath
				}.Concat(Paths.DllSearchPaths))
				{
					if (Utility.TryResolveDllAssembly(assemblyName, item, ref result))
					{
						return result;
					}
				}
				return (Assembly)null;
			};
		}

		public static void Finish()
		{
			foreach (AssemblyDefinition loadedAssembly in LoadedAssemblies)
			{
				try
				{
					loadedAssembly.Dispose();
				}
				catch (Exception)
				{
				}
			}
			LoadedAssemblies.Clear();
			if (TargetTypes.Count > 0 && inError < ErrorLevel.Hard)
			{
				inError = ErrorLevel.Soft;
				Log.LogFatal((object)("Some Injection types have not been found:\n |- " + string.Join("\n |- ", TargetTypes)));
			}
			if (inError > ErrorLevel.None)
			{
				Log.LogWarning((object)"\r\n//////////////////////////////////////////////////////////////////\r\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\r\nAn Error Occurred while injecting code, \r\nthe game is most likely in a broken state and will probably crash!\r\n//////////////////////////////////////////////////////////////////\r\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\");
				if (inError >= ErrorLevel.Hard)
				{
					if (ConsoleManager.ConsoleActive)
					{
						Log.LogWarning((object)"Pausing for 10s to let the user read the logs");
						Thread.Sleep(TimeSpan.FromSeconds(10.0));
					}
					Harmony.CreateAndPatchAll(typeof(TerminationPatch), "mattymatty.MonkeyInjectionLibrary");
				}
			}
			Log.LogInfo((object)"Preloader Finished");
		}

		private static void FindInjections()
		{
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0587: Unknown result type (might be due to invalid IL or missing references)
			//IL_058c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_063d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0642: Unknown result type (might be due to invalid IL or missing references)
			//IL_064b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0652: Expected O, but got Unknown
			Dictionary<string, SortedList<Version, (string, AssemblyDefinition)>> dictionary = new Dictionary<string, SortedList<Version, (string, AssemblyDefinition)>>();
			Log.LogInfo((object)"Searching assemblies with injections");
			string[] files = Directory.GetFiles(Path.GetFullPath(Paths.PluginPath), "*.dll", SearchOption.AllDirectories);
			string[] array = files;
			CustomAttributeArgument val4;
			foreach (string text in array)
			{
				try
				{
					string relativePath = Path.GetRelativePath(Paths.PluginPath, text);
					(string, Version) tuple = default((string, Version));
					AssemblyDefinition val = AssemblyDefinition.ReadAssembly(text, _readerParameters);
					if (!val.HasCustomAttributes)
					{
						val.Dispose();
						continue;
					}
					CustomAttribute val2 = ((IEnumerable<CustomAttribute>)val.CustomAttributes).FirstOrDefault((Func<CustomAttribute, bool>)((CustomAttribute x) => ((MemberReference)x.AttributeType).FullName == RequiresInjectionAttributeName));
					if (val2 == null)
					{
						val.Dispose();
						continue;
					}
					Log.LogDebug((object)("Assembly \"" + relativePath + "\" Wants to inject something"));
					if (((AssemblyNameReference)val.Name).Name != Path.GetFileNameWithoutExtension(text))
					{
						inError = ErrorLevel.Soft;
						Log.LogError((object)("\r\n⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f\r\nFound assembly \"" + relativePath + "\"\r\nwith AssemblyName of \"" + ((AssemblyNameReference)val.Name).Name + "\".\r\nThe file name has to be the same as the AssemblyName!\r\n⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f"));
						continue;
					}
					LoadedAssemblies.AddLast(val);
					CustomAttribute val3 = ((IEnumerable<CustomAttribute>)val.CustomAttributes).FirstOrDefault((Func<CustomAttribute, bool>)((CustomAttribute x) => ((MemberReference)x.AttributeType).FullName == InjectionIdentifierAttributeName));
					if (val3 != null)
					{
						val4 = val3.ConstructorArguments[0];
						string item = (string)((CustomAttributeArgument)(ref val4)).Value;
						val4 = val3.ConstructorArguments[1];
						tuple = (item, new Version((string)((CustomAttributeArgument)(ref val4)).Value));
					}
					else
					{
						Log.LogWarning((object)("Assembly \"" + relativePath + "\" does not have a InjectionIdentifierAttribute, this is deprecated behavior and will be removed in a future release."));
					}
					(string, Version) tuple2 = tuple;
					if (tuple2.Item1 == null && tuple2.Item2 == null)
					{
						CustomAttribute val5 = ((IEnumerable<TypeDefinition>)val.MainModule.Types).SelectMany((TypeDefinition t) => (IEnumerable<CustomAttribute>)t.CustomAttributes).FirstOrDefault((Func<CustomAttribute, bool>)((CustomAttribute x) => ((MemberReference)x.AttributeType).FullName == BepInPluginAttributeName));
						if (val5 != null)
						{
							val4 = val5.ConstructorArguments[0];
							string item2 = (string)((CustomAttributeArgument)(ref val4)).Value;
							val4 = val5.ConstructorArguments[2];
							tuple = (item2, new Version((string)((CustomAttributeArgument)(ref val4)).Value));
						}
					}
					tuple2 = tuple;
					if (tuple2.Item1 == null && tuple2.Item2 == null)
					{
						tuple = (((AssemblyNameReference)val.Name).Name, ((AssemblyNameReference)val.Name).Version);
					}
					Log.LogDebug((object)$"Assembly \"{relativePath}\" is identified as {tuple.Item1} version {tuple.Item2}");
					if (!dictionary.TryGetValue(tuple.Item1, out var value))
					{
						value = new SortedList<Version, (string, AssemblyDefinition)>(InverseComparer<Version>.Default);
					}
					value.Add(tuple.Item2, (text, val));
					dictionary[tuple.Item1] = value;
				}
				catch (BadImageFormatException ex)
				{
					Log.LogWarning((object)("Skipping \"" + Path.GetRelativePath(Paths.PluginPath, text) + "\" because it's not a valid .NET assembly. Full error: " + ex.Message));
				}
				catch (IOException ex2)
				{
					inError = ErrorLevel.Soft;
					Log.LogError((object)("Failed to open \"" + Path.GetRelativePath(Paths.PluginPath, text) + "\". Full error:\n" + ex2.Message));
				}
				catch (Exception arg)
				{
					inError = ErrorLevel.Hard;
					Log.LogFatal((object)$"Exception parsing \"{Path.GetRelativePath(Paths.PluginPath, text)}\":\n{arg}");
					break;
				}
			}
			Log.LogInfo((object)"Extracting injections");
			foreach (var (text3, sortedList2) in dictionary)
			{
				if (sortedList2.Count == 0)
				{
					continue;
				}
				sortedList2.FirstOrDefault().Deconstruct(out var key, out var value2);
				(string, AssemblyDefinition) tuple3 = value2;
				Version arg2 = key;
				string item3 = tuple3.Item1;
				AssemblyDefinition item4 = tuple3.Item2;
				string relativePath2 = Path.GetRelativePath(Paths.PluginPath, item3);
				if (sortedList2.Count > 1)
				{
					string text4 = sortedList2.Skip(1).Aggregate<KeyValuePair<Version, (string, AssemblyDefinition)>, string>($"└►v{arg2} : {relativePath2}", (string a, KeyValuePair<Version, (string path, AssemblyDefinition assembly)> e) => $"├►v{e.Key} : {Path.GetRelativePath(Paths.PluginPath, e.Value.path)}\n{a}");
					Log.LogWarning((object)("\r\n⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f\r\nIdentifier \"" + text3 + "\" has multiple assemblies.\r\n" + text4 + "\r\nonly \"" + relativePath2 + "\" will be loaded, \r\nbut having multiple versions in the DllPath will likely cause issues.\r\n⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f⚠\ufe0f"));
					foreach (var item7 in sortedList2.Values.Skip(1))
					{
						AssemblyDefinition item5 = item7.Item2;
						item5.Dispose();
						LoadedAssemblies.Remove(item5);
					}
				}
				try
				{
					Log.LogDebug((object)("Searching " + text3));
					ErrorHandlingStrategy item6 = ErrorHandlingStrategy.Terminate;
					CustomAttribute val6 = ((IEnumerable<CustomAttribute>)item4.CustomAttributes).FirstOrDefault((Func<CustomAttribute, bool>)((CustomAttribute at) => ((MemberReference)at.AttributeType).FullName == HandleErrorsAttributeName));
					if (val6 != null)
					{
						val4 = val6.ConstructorArguments[0];
						item6 = (ErrorHandlingStrategy)((CustomAttributeArgument)(ref val4)).Value;
					}
					Enumerator<TypeDefinition> enumerator3 = item4.MainModule.Types.GetEnumerator();
					try
					{
						while (enumerator3.MoveNext())
						{
							TypeDefinition current = enumerator3.Current;
							if (!current.HasCustomAttributes)
							{
								continue;
							}
							CustomAttribute[] array2 = ((IEnumerable<CustomAttribute>)current.CustomAttributes).Where((CustomAttribute at) => ((MemberReference)at.AttributeType).FullName == InjectInterfaceAttributeName).ToArray();
							if (!array2.Any())
							{
								continue;
							}
							Log.LogDebug((object)("\tFound " + ((MemberReference)current).FullName));
							CustomAttribute[] array3 = array2;
							foreach (CustomAttribute val7 in array3)
							{
								val4 = val7.ConstructorArguments[0];
								TypeReference val8 = (TypeReference)((CustomAttributeArgument)(ref val4)).Value;
								string text5 = val8.Scope.Name + ".dll";
								string fullName = ((MemberReference)val8).FullName;
								TargetTypes.Add(fullName + " from " + text5);
								if (!Interfaces.TryGetValue(text5, out Dictionary<string, List<(string, TypeDefinition, ErrorHandlingStrategy)>> value3))
								{
									value3 = new Dictionary<string, List<(string, TypeDefinition, ErrorHandlingStrategy)>>();
									Interfaces[text5] = value3;
								}
								if (!value3.TryGetValue(fullName, out var value4))
								{
									value4 = (value3[fullName] = new List<(string, TypeDefinition, ErrorHandlingStrategy)>());
								}
								value4.Add((text3, current, item6));
							}
						}
					}
					finally
					{
						((IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose();
					}
				}
				catch (Exception arg3)
				{
					inError = ErrorLevel.Hard;
					Log.LogFatal((object)$"Exception parsing \"{Path.GetRelativePath(Paths.PluginPath, relativePath2)}\":\n{arg3}");
					break;
				}
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "mattymatty.MonkeyInjectionLibrary";

		public const string PLUGIN_NAME = "MonkeyInjectionLibrary";

		public const string PLUGIN_VERSION = "1.0.3";
	}
}
namespace InjectionLibrary.Utils
{
	internal static class InjectionHelper
	{
		private static class Interfaces
		{
			internal static void ImplementProperties(in TypeDefinition type, TypeDefinition @interface, in HashSet<IMemberDefinition> blacklist, string modIdentifier, ErrorHandlingStrategy errorHandlingStrategy)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				Enumerator<PropertyDefinition> enumerator = @interface.Properties.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						PropertyDefinition current = enumerator.Current;
						ImplementProperty(in type, current, in blacklist, modIdentifier, errorHandlingStrategy);
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
			}

			internal static void ImplementEvents(in TypeDefinition type, TypeDefinition @interface, in HashSet<IMemberDefinition> blacklist, string modIdentifier, ErrorHandlingStrategy errorHandlingStrategy)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				Enumerator<EventDefinition> enumerator = @interface.Events.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						EventDefinition current = enumerator.Current;
						ImplementEvent(in type, current, in blacklist, modIdentifier, errorHandlingStrategy);
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
			}

			internal static void ImplementMethods(in TypeDefinition type, TypeDefinition @interface, in HashSet<IMemberDefinition> blacklist, string modIdentifier, ErrorHandlingStrategy errorHandlingStrategy)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				Enumerator<MethodDefinition> enumerator = @interface.Methods.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						MethodDefinition current = enumerator.Current;
						ImplementMethod(in type, current, in blacklist, modIdentifier, errorHandlingStrategy);
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
			}

			private static void ImplementProperty(in TypeDefinition type, PropertyDefinition property, in HashSet<IMemberDefinition> blacklist, string modIdentifier, ErrorHandlingStrategy errorHandlingStrategy)
			{
				//IL_0228: Unknown result type (might be due to invalid IL or missing references)
				//IL_022f: Expected O, but got Unknown
				//IL_0253: Unknown result type (might be due to invalid IL or missing references)
				//IL_025f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0271: Unknown result type (might be due to invalid IL or missing references)
				//IL_0402: Unknown result type (might be due to invalid IL or missing references)
				//IL_0409: Expected O, but got Unknown
				//IL_0430: Unknown result type (might be due to invalid IL or missing references)
				//IL_043a: Expected O, but got Unknown
				//IL_044a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0456: Unknown result type (might be due to invalid IL or missing references)
				//IL_0462: Unknown result type (might be due to invalid IL or missing references)
				//IL_0474: Unknown result type (might be due to invalid IL or missing references)
				PropertyDefinition propertyImpl = null;
				FieldDefinition backingField = null;
				bool hasImplementation = false;
				if (!blacklist.Add((IMemberDefinition)(object)property))
				{
					return;
				}
				Preloader.Log.LogDebug((object)("Adding Property  '" + ((MemberReference)property).Name + "' to " + ((MemberReference)type).FullName + "'"));
				CustomAttribute val = ((IEnumerable<CustomAttribute>)property.CustomAttributes).FirstOrDefault((Func<CustomAttribute, bool>)((CustomAttribute a) => ((MemberReference)a.AttributeType).FullName == ErrorStrategyAttributeName));
				if (val != null)
				{
					errorHandlingStrategy = val.GetAttributeInstance<HandleErrorsAttribute>().Strategy;
				}
				TypeReference typeRef = ((MemberReference)type).Module.ImportReference(((PropertyReference)property).PropertyType);
				MethodDefinition getMethod = property.GetMethod;
				if (getMethod != null && getMethod.IsAbstract && blacklist.Add((IMemberDefinition)(object)property.GetMethod))
				{
					Preloader.Log.LogDebug((object)("Adding getter of '" + ((MemberReference)property).Name + "' to " + ((MemberReference)type).FullName + "'"));
					MethodDefinition val2 = Extensions.FindMethod(type, "get_" + ((MemberReference)property).Name, true);
					if (val2 != null)
					{
						string injectedIdentifier = val2.GetInjectedIdentifier<MethodDefinition>();
						HandleError("Method 'get_" + ((MemberReference)property).Name + "' is already defined in '" + ((MemberReference)type).FullName + "'" + ((injectedIdentifier != null) ? (" injected by '" + injectedIdentifier + "'") : string.Empty), errorHandlingStrategy);
						val2.Attributes = (MethodAttributes)2502;
					}
					else
					{
						Init(in type, out propertyImpl);
						val2 = new MethodDefinition("get_" + ((MemberReference)property).Name, (MethodAttributes)2502, typeRef);
						val2.MarkAsInjected<MethodDefinition>(((MemberReference)type).Module, modIdentifier);
						ILProcessor iLProcessor = val2.Body.GetILProcessor();
						iLProcessor.Emit(OpCodes.Ldarg_0);
						iLProcessor.Emit(OpCodes.Ldfld, (FieldReference)(object)backingField);
						iLProcessor.Emit(OpCodes.Ret);
						type.Methods.Add(val2);
						propertyImpl.GetMethod = val2;
					}
					((MemberReference)type).Module.CopyCustomAttributes<MethodDefinition>(val2, property.GetMethod);
				}
				getMethod = property.SetMethod;
				if (getMethod != null && getMethod.IsAbstract && blacklist.Add((IMemberDefinition)(object)property.SetMethod))
				{
					Preloader.Log.LogDebug((object)("Adding setter of '" + ((MemberReference)property).Name + "' to " + ((MemberReference)type).FullName + "'"));
					MethodDefinition val3 = Extensions.FindMethod(type, "set_" + ((MemberReference)property).Name, true);
					if (val3 != null)
					{
						string injectedIdentifier2 = val3.GetInjectedIdentifier<MethodDefinition>();
						HandleError("Method 'set_" + ((MemberReference)property).Name + "' is already defined in '" + ((MemberReference)type).FullName + "'" + ((injectedIdentifier2 != null) ? (" injected by '" + injectedIdentifier2 + "'") : string.Empty), errorHandlingStrategy);
						val3.Attributes = (MethodAttributes)2502;
					}
					else
					{
						if (!hasImplementation)
						{
							Init(in type, out propertyImpl);
						}
						val3 = new MethodDefinition("set_" + ((MemberReference)property).Name, (MethodAttributes)2502, ((MemberReference)type).Module.TypeSystem.Void);
						val3.MarkAsInjected<MethodDefinition>(((MemberReference)type).Module, modIdentifier);
						((MethodReference)val3).Parameters.Add(new ParameterDefinition("value", (ParameterAttributes)0, typeRef));
						ILProcessor iLProcessor2 = val3.Body.GetILProcessor();
						iLProcessor2.Emit(OpCodes.Ldarg_0);
						iLProcessor2.Emit(OpCodes.Ldarg_1);
						iLProcessor2.Emit(OpCodes.Stfld, (FieldReference)(object)backingField);
						iLProcessor2.Emit(OpCodes.Ret);
						type.Methods.Add(val3);
						propertyImpl.SetMethod = val3;
					}
					((MemberReference)type).Module.CopyCustomAttributes<MethodDefinition>(val3, property.SetMethod);
				}
				if (!hasImplementation)
				{
					Preloader.Log.LogDebug((object)("Default Property '" + ((MemberReference)property).Name + "' to " + ((MemberReference)type).FullName + "'"));
				}
				else
				{
					type.Fields.TryAdd<FieldDefinition>(backingField);
					type.Properties.TryAdd<PropertyDefinition>(propertyImpl);
				}
				void Init(in TypeDefinition reference2, out PropertyDefinition reference)
				{
					//IL_0054: Unknown result type (might be due to invalid IL or missing references)
					//IL_005e: Expected O, but got Unknown
					//IL_0112: Unknown result type (might be due to invalid IL or missing references)
					//IL_0118: Expected O, but got Unknown
					reference = null;
					backingField = Extensions.FindField(reference2, "<" + ((MemberReference)property).Name + ">k__BackingField");
					if (backingField == null)
					{
						backingField = new FieldDefinition("<" + ((MemberReference)property).Name + ">k__BackingField", (FieldAttributes)1, typeRef);
						backingField.MarkAsInjected<FieldDefinition>(((MemberReference)reference2).Module, modIdentifier);
					}
					else
					{
						string injectedIdentifier3 = backingField.GetInjectedIdentifier<FieldDefinition>();
						HandleError("Field '<" + ((MemberReference)property).Name + ">k__BackingField' already exists in " + ((MemberReference)reference2).FullName + "'" + ((injectedIdentifier3 != null) ? (" injected by '" + injectedIdentifier3 + "'") : string.Empty), errorHandlingStrategy);
					}
					reference = Extensions.FindProperty(reference2, ((MemberReference)property).Name);
					if (reference == null)
					{
						reference = new PropertyDefinition(((MemberReference)property).Name, (PropertyAttributes)0, typeRef);
						((MemberReference)reference2).Module.CopyCustomAttributes<PropertyDefinition>(reference, property);
						reference.MarkAsInjected<PropertyDefinition>(((MemberReference)reference2).Module, modIdentifier);
					}
					else
					{
						string injectedIdentifier4 = reference.GetInjectedIdentifier<PropertyDefinition>();
						HandleError("Property '" + ((MemberReference)property).Name + "' already exists in " + ((MemberReference)reference2).FullName + "'" + ((injectedIdentifier4 != null) ? (" injected by '" + injectedIdentifier4 + "'") : string.Empty), errorHandlingStrategy);
					}
					hasImplementation = true;
				}
			}

			private static void ImplementEvent(in TypeDefinition type, EventDefinition @event, in HashSet<IMemberDefinition> blacklist, string modIdentifier, ErrorHandlingStrategy errorHandlingStrategy)
			{
				//IL_0233: Unknown result type (might be due to invalid IL or missing references)
				//IL_023a: Expected O, but got Unknown
				//IL_0261: Unknown result type (might be due to invalid IL or missing references)
				//IL_026b: Expected O, but got Unknown
				//IL_027b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0287: Unknown result type (might be due to invalid IL or missing references)
				//IL_0293: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0314: Unknown result type (might be due to invalid IL or missing references)
				//IL_0326: Unknown result type (might be due to invalid IL or missing references)
				//IL_04b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_04be: Expected O, but got Unknown
				//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_04ef: Expected O, but got Unknown
				//IL_04ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_050b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0517: Unknown result type (might be due to invalid IL or missing references)
				//IL_0529: Unknown result type (might be due to invalid IL or missing references)
				//IL_0535: Unknown result type (might be due to invalid IL or missing references)
				//IL_0581: Unknown result type (might be due to invalid IL or missing references)
				//IL_0598: Unknown result type (might be due to invalid IL or missing references)
				//IL_05aa: Unknown result type (might be due to invalid IL or missing references)
				//IL_073b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0742: Expected O, but got Unknown
				//IL_0766: Unknown result type (might be due to invalid IL or missing references)
				//IL_076b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0788: Unknown result type (might be due to invalid IL or missing references)
				//IL_07a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_07aa: Expected O, but got Unknown
				//IL_07d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_07df: Unknown result type (might be due to invalid IL or missing references)
				//IL_07f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_081c: Unknown result type (might be due to invalid IL or missing references)
				//IL_086d: Unknown result type (might be due to invalid IL or missing references)
				EventDefinition eventImpl = null;
				FieldDefinition backingField = null;
				bool hasImplementation = false;
				if (!blacklist.Add((IMemberDefinition)(object)@event))
				{
					return;
				}
				Preloader.Log.LogDebug((object)("Adding Event     '" + ((MemberReference)@event).Name + "' to " + ((MemberReference)type).FullName + "'"));
				CustomAttribute val = ((IEnumerable<CustomAttribute>)@event.CustomAttributes).FirstOrDefault((Func<CustomAttribute, bool>)((CustomAttribute a) => ((MemberReference)a.AttributeType).FullName == ErrorStrategyAttributeName));
				if (val != null)
				{
					errorHandlingStrategy = val.GetAttributeInstance<HandleErrorsAttribute>().Strategy;
				}
				TypeReference typeRef = ((MemberReference)type).Module.ImportReference(((EventReference)@event).EventType);
				MethodDefinition addMethod = @event.AddMethod;
				if (addMethod != null && addMethod.IsAbstract && blacklist.Add((IMemberDefinition)(object)@event.AddMethod))
				{
					Preloader.Log.LogDebug((object)("Adding add of    '" + ((MemberReference)@event).Name + "' to " + ((MemberReference)type).FullName + "'"));
					MethodDefinition val2 = Extensions.FindMethod(type, "add_" + ((MemberReference)@event).Name, true);
					if (val2 != null)
					{
						string injectedIdentifier = val2.GetInjectedIdentifier<MethodDefinition>();
						HandleError("Method 'add_" + ((MemberReference)@event).Name + "' is already defined in '" + ((MemberReference)type).FullName + "'" + ((injectedIdentifier != null) ? (" injected by '" + injectedIdentifier + "'") : string.Empty), errorHandlingStrategy);
						val2.Attributes = (MethodAttributes)2502;
					}
					else
					{
						Init(in type, out eventImpl);
						val2 = new MethodDefinition("add_" + ((MemberReference)@event).Name, (MethodAttributes)2502, ((MemberReference)type).Module.TypeSystem.Void);
						val2.MarkAsInjected<MethodDefinition>(((MemberReference)type).Module, modIdentifier);
						((MethodReference)val2).Parameters.Add(new ParameterDefinition("value", (ParameterAttributes)0, typeRef));
						ILProcessor iLProcessor = val2.Body.GetILProcessor();
						iLProcessor.Emit(OpCodes.Ldarg_0);
						iLProcessor.Emit(OpCodes.Ldarg_0);
						iLProcessor.Emit(OpCodes.Ldfld, (FieldReference)(object)backingField);
						iLProcessor.Emit(OpCodes.Ldarg_1);
						iLProcessor.Emit(OpCodes.Call, ((MemberReference)type).Module.ImportReference((MethodBase)typeof(Delegate).GetMethod("Combine", new Type[2]
						{
							typeof(Delegate),
							typeof(Delegate)
						})));
						iLProcessor.Emit(OpCodes.Castclass, ((EventReference)@event).EventType);
						iLProcessor.Emit(OpCodes.Stfld, (FieldReference)(object)backingField);
						iLProcessor.Emit(OpCodes.Ret);
						type.Methods.Add(val2);
						eventImpl.AddMethod = val2;
					}
					((MemberReference)type).Module.CopyCustomAttributes<MethodDefinition>(val2, @event.AddMethod);
				}
				addMethod = @event.RemoveMethod;
				if (addMethod != null && addMethod.IsAbstract && blacklist.Add((IMemberDefinition)(object)@event.RemoveMethod))
				{
					if (!hasImplementation)
					{
						Init(in type, out eventImpl);
					}
					Preloader.Log.LogDebug((object)("Adding remove of '" + ((MemberReference)@event).Name + "' to " + ((MemberReference)type).FullName + "'"));
					MethodDefinition val3 = Extensions.FindMethod(type, "remove_" + ((MemberReference)@event).Name, true);
					if (val3 != null)
					{
						string injectedIdentifier2 = val3.GetInjectedIdentifier<MethodDefinition>();
						HandleError("Method 'remove_" + ((MemberReference)@event).Name + "' is already defined in '" + ((MemberReference)type).FullName + "'" + ((injectedIdentifier2 != null) ? (" injected by '" + injectedIdentifier2 + "'") : string.Empty), errorHandlingStrategy);
						val3.Attributes = (MethodAttributes)2502;
					}
					else
					{
						val3 = new MethodDefinition("remove_" + ((MemberReference)@event).Name, (MethodAttributes)2502, ((MemberReference)type).Module.TypeSystem.Void);
						val3.MarkAsInjected<MethodDefinition>(((MemberReference)type).Module, modIdentifier);
						((MethodReference)val3).Parameters.Add(new ParameterDefinition("value", (ParameterAttributes)0, typeRef));
						ILProcessor iLProcessor2 = val3.Body.GetILProcessor();
						iLProcessor2.Emit(OpCodes.Ldarg_0);
						iLProcessor2.Emit(OpCodes.Ldarg_0);
						iLProcessor2.Emit(OpCodes.Ldfld, (FieldReference)(object)backingField);
						iLProcessor2.Emit(OpCodes.Ldarg_1);
						iLProcessor2.Emit(OpCodes.Call, ((MemberReference)type).Module.ImportReference((MethodBase)typeof(Delegate).GetMethod("Remove", new Type[2]
						{
							typeof(Delegate),
							typeof(Delegate)
						})));
						iLProcessor2.Emit(OpCodes.Castclass, ((EventReference)@event).EventType);
						iLProcessor2.Emit(OpCodes.Stfld, (FieldReference)(object)backingField);
						iLProcessor2.Emit(OpCodes.Ret);
						type.Methods.Add(val3);
						eventImpl.RemoveMethod = val3;
					}
					((MemberReference)type).Module.CopyCustomAttributes<MethodDefinition>(val3, @event.RemoveMethod);
				}
				addMethod = @event.InvokeMethod;
				if (addMethod != null && addMethod.IsAbstract && blacklist.Add((IMemberDefinition)(object)@event.InvokeMethod))
				{
					Preloader.Log.LogDebug((object)("Adding raise of  '" + ((MemberReference)@event).Name + "' to " + ((MemberReference)type).FullName + "'"));
					MethodDefinition val4 = Extensions.FindMethod(type, "raise_" + ((MemberReference)@event).Name, true);
					if (val4 != null)
					{
						string injectedIdentifier3 = val4.GetInjectedIdentifier<MethodDefinition>();
						HandleError("Method 'raise_" + ((MemberReference)@event).Name + "' is already defined in '" + ((MemberReference)type).FullName + "'" + ((injectedIdentifier3 != null) ? (" injected by '" + injectedIdentifier3 + "'") : string.Empty), errorHandlingStrategy);
						val4.Attributes = (MethodAttributes)2502;
					}
					else
					{
						if (!hasImplementation)
						{
							Init(in type, out eventImpl);
						}
						val4 = new MethodDefinition("raise_" + ((MemberReference)@event).Name, (MethodAttributes)2502, ((MemberReference)type).Module.TypeSystem.Void);
						val4.MarkAsInjected<MethodDefinition>(((MemberReference)type).Module, modIdentifier);
						Enumerator<ParameterDefinition> enumerator = ((MethodReference)@event.InvokeMethod).Parameters.GetEnumerator();
						try
						{
							while (enumerator.MoveNext())
							{
								ParameterDefinition current = enumerator.Current;
								((MethodReference)val4).Parameters.Add(new ParameterDefinition(((ParameterReference)current).Name, current.Attributes, ((MemberReference)type).Module.ImportReference(((ParameterReference)current).ParameterType)));
							}
						}
						finally
						{
							((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
						}
						ILProcessor iLProcessor3 = val4.Body.GetILProcessor();
						iLProcessor3.Emit(OpCodes.Ldarg_0);
						iLProcessor3.Emit(OpCodes.Ldfld, (FieldReference)(object)backingField);
						for (int num = 0; num < ((MethodReference)val4).Parameters.Count; num++)
						{
							iLProcessor3.Emit(OpCodes.Ldarg, num + 1);
						}
						iLProcessor3.Emit(OpCodes.Callvirt, ((MemberReference)type).Module.ImportReference((MethodReference)(object)((IEnumerable<MethodDefinition>)((EventReference)@event).EventType.Resolve().Methods).First((MethodDefinition m) => ((MemberReference)m).Name == "Invoke")));
						iLProcessor3.Emit(OpCodes.Ret);
						type.Methods.Add(val4);
						eventImpl.InvokeMethod = val4;
					}
					((MemberReference)type).Module.CopyCustomAttributes<MethodDefinition>(val4, @event.InvokeMethod);
				}
				if (hasImplementation)
				{
					type.Fields.TryAdd<FieldDefinition>(backingField);
					type.Events.TryAdd<EventDefinition>(eventImpl);
				}
				void Init(in TypeDefinition reference2, out EventDefinition reference)
				{
					//IL_0036: Unknown result type (might be due to invalid IL or missing references)
					//IL_0040: Expected O, but got Unknown
					//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
					//IL_00fa: Expected O, but got Unknown
					reference = null;
					backingField = Extensions.FindField(reference2, ((MemberReference)@event).Name);
					if (backingField == null)
					{
						backingField = new FieldDefinition(((MemberReference)@event).Name, (FieldAttributes)1, typeRef);
						backingField.MarkAsInjected<FieldDefinition>(((MemberReference)reference2).Module, modIdentifier);
					}
					else
					{
						string injectedIdentifier4 = backingField.GetInjectedIdentifier<FieldDefinition>();
						HandleError("Field '" + ((MemberReference)@event).Name + "' already exists in " + ((MemberReference)reference2).FullName + "'" + ((injectedIdentifier4 != null) ? (" injected by '" + injectedIdentifier4 + "'") : string.Empty), errorHandlingStrategy);
					}
					reference = Extensions.FindEvent(reference2, ((MemberReference)@event).Name);
					if (reference == null)
					{
						reference = new EventDefinition(((MemberReference)@event).Name, (EventAttributes)0, typeRef);
						((MemberReference)reference2).Module.CopyCustomAttributes<EventDefinition>(reference, @event);
						reference.MarkAsInjected<EventDefinition>(((MemberReference)reference2).Module, modIdentifier);
					}
					else
					{
						string injectedIdentifier5 = reference.GetInjectedIdentifier<EventDefinition>();
						HandleError("Event '" + ((MemberReference)@event).Name + "' already exists in " + ((MemberReference)reference2).FullName + "'" + ((injectedIdentifier5 != null) ? (" injected by '" + injectedIdentifier5 + "'") : string.Empty), errorHandlingStrategy);
					}
					hasImplementation = true;
				}
			}

			private static void ImplementMethod(in TypeDefinition type, MethodDefinition method, in HashSet<IMemberDefinition> blacklist, string modIdentifier, ErrorHandlingStrategy errorHandlingStrategy)
			{
				//IL_012f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0135: Expected O, but got Unknown
				//IL_013b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0140: Unknown result type (might be due to invalid IL or missing references)
				//IL_015c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0174: Unknown result type (might be due to invalid IL or missing references)
				//IL_017e: Expected O, but got Unknown
				//IL_0219: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_020c: Unknown result type (might be due to invalid IL or missing references)
				if (!blacklist.Add((IMemberDefinition)(object)method))
				{
					return;
				}
				Preloader.Log.LogDebug((object)("Adding Method    '" + ((MemberReference)method).Name + "' to " + ((MemberReference)type).FullName + "'"));
				if (!method.IsAbstract)
				{
					return;
				}
				CustomAttribute val = ((IEnumerable<CustomAttribute>)method.CustomAttributes).FirstOrDefault((Func<CustomAttribute, bool>)((CustomAttribute a) => ((MemberReference)a.AttributeType).FullName == ErrorStrategyAttributeName));
				if (val != null)
				{
					errorHandlingStrategy = val.GetAttributeInstance<HandleErrorsAttribute>().Strategy;
				}
				MethodDefinition val2 = Extensions.FindMethod(type, ((MemberReference)method).Name, true);
				if (val2 != null)
				{
					string injectedIdentifier = method.GetInjectedIdentifier<MethodDefinition>();
					HandleError("Method '" + ((MemberReference)method).Name + "' is already defined in '" + ((MemberReference)type).FullName + "'" + ((injectedIdentifier != null) ? (" injected by '" + injectedIdentifier + "'") : string.Empty), errorHandlingStrategy);
					val2.Attributes = (MethodAttributes)326;
				}
				else
				{
					val2 = new MethodDefinition(((MemberReference)method).Name, (MethodAttributes)326, ((MemberReference)type).Module.ImportReference(((MethodReference)method).ReturnType));
					Enumerator<ParameterDefinition> enumerator = ((MethodReference)method).Parameters.GetEnumerator();
					try
					{
						while (enumerator.MoveNext())
						{
							ParameterDefinition current = enumerator.Current;
							((MethodReference)val2).Parameters.Add(new ParameterDefinition(((ParameterReference)current).Name, current.Attributes, ((MemberReference)type).Module.ImportReference(((ParameterReference)current).ParameterType)));
						}
					}
					finally
					{
						((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
					}
					ILProcessor iLProcessor = val2.Body.GetILProcessor();
					if (((MemberReference)((MethodReference)method).ReturnType).FullName != "System.Void")
					{
						ConstructorInfo constructor = typeof(NotImplementedException).GetConstructor(new Type[1] { typeof(string) });
						MethodReference val3 = ((MemberReference)type).Module.ImportReference((MethodBase)constructor);
						iLProcessor.Emit(OpCodes.Ldstr, "This is a Stub");
						iLProcessor.Emit(OpCodes.Newobj, val3);
						iLProcessor.Emit(OpCodes.Throw);
					}
					else
					{
						iLProcessor.Emit(OpCodes.Ret);
					}
					val2.MarkAsInjected<MethodDefinition>(((MemberReference)type).Module, modIdentifier);
				}
				((MemberReference)type).Module.CopyCustomAttributes<MethodDefinition>(val2, method);
				type.Methods.TryAdd<MethodDefinition>(val2);
			}
		}

		private static readonly string ErrorStrategyAttributeName = typeof(HandleErrorsAttribute).FullName;

		private const MethodAttributes InterfaceMethodAttributes = (MethodAttributes)326;

		private const MethodAttributes InterfaceSpecialMethodAttributes = (MethodAttributes)2502;

		private const PropertyAttributes InterfacePropertyAttributes = (PropertyAttributes)0;

		private const EventAttributes InterfaceEventAttributes = (EventAttributes)0;

		public static T GetAttributeInstance<T>(this CustomAttribute attribute) where T : Attribute
		{
			Type typeFromHandle = typeof(T);
			object[] args = ((IEnumerable<CustomAttributeArgument>)attribute.ConstructorArguments).Select((CustomAttributeArgument ca) => ((CustomAttributeArgument)(ref ca)).Value).ToArray();
			return (T)Activator.CreateInstance(typeFromHandle, args);
		}

		private static void HandleError(string message, ErrorHandlingStrategy strategy)
		{
			switch (strategy)
			{
			default:
				Preloader.inError = ErrorLevel.Hard;
				Preloader.Log.LogFatal((object)message);
				throw new TerminationException("Fatal Injection error!");
			case ErrorHandlingStrategy.LogWarning:
				Preloader.Log.LogWarning((object)message);
				break;
			case ErrorHandlingStrategy.LogError:
				Preloader.inError = ErrorLevel.Soft;
				Preloader.Log.LogError((object)message);
				break;
			case ErrorHandlingStrategy.Ignore:
				break;
			}
		}

		internal static void ImplementInterface(this TypeDefinition self, TypeReference @interface, string modIdentifier, ErrorHandlingStrategy errorHandlingStrategy)
		{
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Expected O, but got Unknown
			TypeDefinition val = @interface.Resolve();
			CustomAttribute val2 = ((IEnumerable<CustomAttribute>)val.CustomAttributes).FirstOrDefault((Func<CustomAttribute, bool>)((CustomAttribute a) => ((MemberReference)a.AttributeType).FullName == ErrorStrategyAttributeName));
			if (val2 != null)
			{
				errorHandlingStrategy = val2.GetAttributeInstance<HandleErrorsAttribute>().Strategy;
			}
			if (!val.IsInterface)
			{
				HandleError("Type '" + ((MemberReference)@interface).FullName + "' from '" + modIdentifier + "' is not an interface!", errorHandlingStrategy);
				return;
			}
			if (((TypeReference)val).HasGenericParameters)
			{
				HandleError("Type '" + ((MemberReference)@interface).FullName + "' from '" + modIdentifier + "' is a Generic type!", errorHandlingStrategy);
				return;
			}
			Preloader.Log.LogDebug((object)("Injecting '" + ((MemberReference)@interface).FullName + "' from '" + modIdentifier + "' into " + ((MemberReference)self).FullName + "'"));
			if (((IEnumerable<InterfaceImplementation>)self.Interfaces).Any((InterfaceImplementation i) => i.InterfaceType == @interface))
			{
				Preloader.Log.LogWarning((object)("Interface '" + ((MemberReference)@interface).FullName + "' from '" + modIdentifier + "' is already implemented, SKIPPING!"));
				return;
			}
			Enumerator<InterfaceImplementation> enumerator = val.Interfaces.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					InterfaceImplementation current = enumerator.Current;
					self.ImplementInterface(current.InterfaceType, modIdentifier, errorHandlingStrategy);
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			TypeReference val3 = ((MemberReference)self).Module.ImportReference(@interface);
			HashSet<IMemberDefinition> blacklist = new HashSet<IMemberDefinition>();
			Interfaces.ImplementProperties(in self, val, in blacklist, modIdentifier, errorHandlingStrategy);
			Interfaces.ImplementEvents(in self, val, in blacklist, modIdentifier, errorHandlingStrategy);
			Interfaces.ImplementMethods(in self, val, in blacklist, modIdentifier, errorHandlingStrategy);
			self.Interfaces.Add(new InterfaceImplementation(val3));
		}

		private static void MarkAsInjected<T>(this T target, ModuleDefinition module, string modIdentifier) where T : MemberReference, ICustomAttributeProvider
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			module.ImportReference(typeof(InjectedMemberAttribute));
			MethodReference val = module.ImportReference((MethodBase)typeof(InjectedMemberAttribute).GetConstructor(AccessTools.all, null, new Type[1] { typeof(string) }, Array.Empty<ParameterModifier>()));
			CustomAttribute val2 = new CustomAttribute(val);
			val2.ConstructorArguments.Add(new CustomAttributeArgument(module.ImportReference(typeof(string)), (object)modIdentifier));
			((ICustomAttributeProvider)target).CustomAttributes.Add(val2);
		}

		private static string GetInjectedIdentifier<T>(this T target) where T : MemberReference, ICustomAttributeProvider
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Enumerator<CustomAttribute> enumerator = ((ICustomAttributeProvider)target).CustomAttributes.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					CustomAttribute current = enumerator.Current;
					if (((MemberReference)current.AttributeType).FullName == typeof(InjectedMemberAttribute).FullName)
					{
						object result;
						if (current.ConstructorArguments.Count <= 0)
						{
							result = null;
						}
						else
						{
							CustomAttributeArgument val = current.ConstructorArguments[0];
							result = ((CustomAttributeArgument)(ref val)).Value.ToString();
						}
						return (string)result;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			return null;
		}

		private static void CopyCustomAttributes<T>(this ModuleDefinition module, T target, T source) where T : MemberReference, ICustomAttributeProvider
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			if (((MemberReference)target).Module != null && ((MemberReference)target).Module != module)
			{
				throw new InvalidOperationException("Cannot copy custom attributes between different modules.");
			}
			Enumerator<CustomAttribute> enumerator = ((ICustomAttributeProvider)source).CustomAttributes.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					CustomAttribute current = enumerator.Current;
					if (!(((MemberReference)current.AttributeType).FullName == ErrorStrategyAttributeName))
					{
						MethodReference val = module.ImportReference(current.Constructor);
						CustomAttribute val2 = new CustomAttribute(val, current.GetBlob());
						((ICustomAttributeProvider)target).CustomAttributes.Add(val2);
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void TryAdd<T>(this Collection<T> collection, T newMember) where T : IMemberDefinition
		{
			if (!((IEnumerable<T>)collection).Any((T member) => ((IMemberDefinition)member).Name == ((IMemberDefinition)newMember).Name))
			{
				collection.Add(newMember);
			}
		}

		internal static string GetAssemblyQualifiedName(this TypeReference type)
		{
			IMetadataScope scope = type.Scope;
			AssemblyNameReference val = (AssemblyNameReference)(object)((scope is AssemblyNameReference) ? scope : null);
			string text;
			if (val == null)
			{
				ModuleDefinition val2 = (ModuleDefinition)(object)((scope is ModuleDefinition) ? scope : null);
				if (val2 != null)
				{
					AssemblyDefinition assembly = val2.Assembly;
					object obj;
					if (assembly == null)
					{
						obj = null;
					}
					else
					{
						AssemblyNameDefinition name = assembly.Name;
						obj = ((name != null) ? ((AssemblyNameReference)name).FullName : null);
					}
					text = (string)obj;
				}
				else
				{
					text = null;
				}
			}
			else
			{
				text = val.FullName;
			}
			string text2 = text;
			if (text2 == null)
			{
				return ((MemberReference)type).FullName;
			}
			return ((MemberReference)type).FullName + ", " + text2;
		}
	}
	public sealed class InverseComparer<T> : IComparer<T>
	{
		public static readonly InverseComparer<T> Default = new InverseComparer<T>(Comparer<T>.Default);

		private readonly IComparer<T> _comparer;

		public static InverseComparer<T> Reverse(IComparer<T> comparer)
		{
			return new InverseComparer<T>(comparer);
		}

		private InverseComparer(IComparer<T> comparer)
		{
			_comparer = comparer;
		}

		public int Compare(T x, T y)
		{
			return _comparer.Compare(y, x);
		}
	}
}
namespace InjectionLibrary.Patches
{
	[HarmonyPatch(typeof(Chainloader))]
	internal static class TerminationPatch
	{
		[HarmonyPatch("ReplayPreloaderLogs")]
		[HarmonyFinalizer]
		internal static void TerminateAfterLogging()
		{
			Preloader.Log.LogFatal((object)"An unrecoverable error occurred. Shutting down the process.");
			Environment.Exit(999);
		}
	}
}
namespace InjectionLibrary.Exceptions
{
	public class TerminationException : Exception
	{
		public TerminationException(string message)
			: base(message)
		{
		}
	}
}
namespace InjectionLibrary.Attributes
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Interface)]
	public class HandleErrorsAttribute : Attribute
	{
		public ErrorHandlingStrategy Strategy { get; }

		public HandleErrorsAttribute(ErrorHandlingStrategy strategy)
		{
			Strategy = strategy;
		}

		public HandleErrorsAttribute(int strategy)
		{
			Strategy = (ErrorHandlingStrategy)strategy;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event, AllowMultiple = true)]
	public sealed class InjectedMemberAttribute : Attribute
	{
		public string Identifier { get; }

		private InjectedMemberAttribute(string id)
		{
			Identifier = id;
		}
	}
	[AttributeUsage(AttributeTargets.Interface, AllowMultiple = true)]
	public sealed class InjectInterfaceAttribute(Type targetType) : Attribute()
	{
		public string AssemblyName => targetType.Assembly.GetName().Name;

		public string TypeName => targetType.FullName;
	}
	[AttributeUsage(AttributeTargets.Assembly)]
	public sealed class InjectionIdentifierAttribute : Attribute
	{
		public string Identifier { get; }

		public Version Version { get; }

		public InjectionIdentifierAttribute(string identifier, string version)
		{
			Identifier = identifier;
			Version = new Version(version);
			base..ctor();
		}
	}
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	public sealed class RequiresInjectionsAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}