Decompiled source of AdvancedREPO Patcher v1.0.0

BepInEx/patchers/AdvancedREPO.Patcher.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using Mono.Collections.Generic;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AdvancedREPO.Patcher")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Better stamina for REPO")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e0ce9281b74a83533d1745f48a75808927f50012")]
[assembly: AssemblyProduct("AdvancedREPO.Patcher")]
[assembly: AssemblyTitle("AdvancedREPO.Patcher")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 AdvancedREPO.Patcher
{
	public class Patch : Attribute
	{
		public string? TypeName = null;

		private string _AssemblyName = "Assembly-CSharp.dll";

		public string? MethodName { get; set; } = null;


		public string AssemblyName
		{
			get
			{
				return _AssemblyName;
			}
			set
			{
				if (!value.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
				{
					value += ".dll";
				}
				_AssemblyName = value;
			}
		}

		public Patch(string? typeName = null)
		{
			TypeName = typeName;
		}
	}
	public class Patcher
	{
		public static ManualLogSource Log;

		private static List<string>? AssemblyNames;

		private static ConcurrentDictionary<string, ConcurrentBag<Action<AssemblyDefinition>>>? Assemblies;

		private static ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentBag<Action<TypeDefinition>>>>? Types;

		private static ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentBag<Action<MethodDefinition>>>>>? Methods;

		private static bool Initialized;

		public static IEnumerable<string> TargetDLLs
		{
			get
			{
				Log = Logger.CreateLogSource("AdvancedREPO.Patcher");
				Assembly callingAssembly = Assembly.GetCallingAssembly();
				string name = callingAssembly.GetName().Name;
				if (!name.StartsWith("BepInEx", StringComparison.OrdinalIgnoreCase))
				{
					AssemblyNames = null;
					Assemblies = new ConcurrentDictionary<string, ConcurrentBag<Action<AssemblyDefinition>>>();
					Types = new ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentBag<Action<TypeDefinition>>>>();
					Methods = new ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentBag<Action<MethodDefinition>>>>>();
					Log.LogInfo((object)("Collecting patches for assembly " + callingAssembly.GetName().Name));
					Initialize(callingAssembly);
					if (AssemblyNames != null)
					{
						return AssemblyNames;
					}
					Log.LogWarning((object)"No targetted dlls found. Skipping patching.");
				}
				return new string[0];
			}
		}

		public static void Initialize(Assembly assembly)
		{
			if (!assembly.GetReferencedAssemblies().Any((AssemblyName e) => e.Name == "AdvancedREPO.Patcher"))
			{
				return;
			}
			assembly.GetTypes().AsParallel().ForAll(delegate(Type type)
			{
				type.GetMethods().AsParallel().ForAll(delegate(MethodInfo method)
				{
					Patch customAttribute = method.GetCustomAttribute<Patch>();
					if (customAttribute == null)
					{
						return;
					}
					if (customAttribute.TypeName != null)
					{
						if (customAttribute.MethodName != null)
						{
							try
							{
								Methods.GetOrAdd(customAttribute.AssemblyName, (string key) => new ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentBag<Action<MethodDefinition>>>>()).GetOrAdd(customAttribute.TypeName, (string key) => new ConcurrentDictionary<string, ConcurrentBag<Action<MethodDefinition>>>()).GetOrAdd(customAttribute.MethodName, (string key) => new ConcurrentBag<Action<MethodDefinition>>())
									.Add((Action<MethodDefinition>)method.CreateDelegate(typeof(Action<MethodDefinition>)));
								return;
							}
							catch (Exception)
							{
								Log.LogWarning((object)("Method patcher found in " + method.DeclaringType.FullName + "::" + method.Name + " has an invalid signature."));
								return;
							}
						}
						try
						{
							Types.GetOrAdd(customAttribute.AssemblyName, (string key) => new ConcurrentDictionary<string, ConcurrentBag<Action<TypeDefinition>>>()).GetOrAdd(customAttribute.TypeName, (string key) => new ConcurrentBag<Action<TypeDefinition>>()).Add((Action<TypeDefinition>)method.CreateDelegate(typeof(Action<TypeDefinition>)));
							return;
						}
						catch (Exception)
						{
							Log.LogWarning((object)("Type patcher found in " + method.DeclaringType.FullName + "::" + method.Name + " has an invalid signature."));
							return;
						}
					}
					try
					{
						Assemblies.GetOrAdd(customAttribute.AssemblyName, (string key) => new ConcurrentBag<Action<AssemblyDefinition>>()).Add((Action<AssemblyDefinition>)method.CreateDelegate(typeof(Action<AssemblyDefinition>)));
					}
					catch (Exception)
					{
						Log.LogWarning((object)("Assembly patcher found in " + method.DeclaringType.FullName + "::" + method.Name + " has an invalid signature."));
					}
				});
			});
			HashSet<string> assemblies = new HashSet<string>();
			Methods.Keys.ToList().ForEach(delegate(string key)
			{
				assemblies.Add(key);
			});
			Types.Keys.ToList().ForEach(delegate(string key)
			{
				assemblies.Add(key);
			});
			Assemblies.Keys.ToList().ForEach(delegate(string key)
			{
				assemblies.Add(key);
			});
			AssemblyNames = assemblies.ToList();
		}

		public static void Patch(AssemblyDefinition assembly)
		{
			AssemblyDefinition assembly2 = assembly;
			Log.LogInfo((object)("Patching assembly " + ((AssemblyNameReference)assembly2.Name).Name));
			string key = ((AssemblyNameReference)assembly2.Name).Name + ".dll";
			if (Assemblies.TryGetValue(key, out ConcurrentBag<Action<AssemblyDefinition>> value))
			{
				Log.LogInfo((object)("Applying patches for assembly " + ((AssemblyNameReference)assembly2.Name).Name));
				value.AsParallel().ForAll(delegate(Action<AssemblyDefinition> p)
				{
					p(assembly2);
				});
			}
			if (Types.TryGetValue(key, out ConcurrentDictionary<string, ConcurrentBag<Action<TypeDefinition>>> value2))
			{
				value2.AsParallel().ForAll(delegate(KeyValuePair<string, ConcurrentBag<Action<TypeDefinition>>> t)
				{
					ModuleDefinition mainModule2 = assembly2.MainModule;
					TypeDefinition type2 = ((mainModule2 != null) ? mainModule2.GetType(t.Key) : null) ?? null;
					if (type2 != null)
					{
						Log.LogInfo((object)("Applying patches for type " + ((MemberReference)type2).FullName));
						t.Value.AsParallel().ForAll(delegate(Action<TypeDefinition> p)
						{
							p(type2);
						});
					}
				});
			}
			if (!Methods.TryGetValue(key, out ConcurrentDictionary<string, ConcurrentDictionary<string, ConcurrentBag<Action<MethodDefinition>>>> value3))
			{
				return;
			}
			value3.AsParallel().ForAll(delegate(KeyValuePair<string, ConcurrentDictionary<string, ConcurrentBag<Action<MethodDefinition>>>> t)
			{
				ModuleDefinition mainModule = assembly2.MainModule;
				TypeDefinition type = ((mainModule != null) ? mainModule.GetType(t.Key) : null) ?? null;
				if (type != null)
				{
					t.Value.AsParallel().ForAll(delegate(KeyValuePair<string, ConcurrentBag<Action<MethodDefinition>>> m)
					{
						IEnumerable<MethodDefinition> methods = TypeDefinitionRocks.GetMethods(type);
						methods.AsParallel().ForAll(delegate(MethodDefinition method)
						{
							if (((MemberReference)method).Name == m.Key)
							{
								Log.LogInfo((object)("Applying patches for method " + ((MemberReference)method).FullName));
								m.Value.AsParallel().ForAll(delegate(Action<MethodDefinition> p)
								{
									p(method);
								});
							}
						});
					});
				}
			});
		}

		public static void Finish()
		{
			Log.Dispose();
		}
	}
}
namespace AdvancedREPO.Patcher.Extensions
{
	public static class Instructions
	{
		private static Dictionary<OpCode, OpCode> SimplifyDict = new Dictionary<OpCode, OpCode>
		{
			{
				OpCodes.Beq_S,
				OpCodes.Beq
			},
			{
				OpCodes.Bge_S,
				OpCodes.Bge
			},
			{
				OpCodes.Bge_Un_S,
				OpCodes.Bge_Un
			},
			{
				OpCodes.Bgt_S,
				OpCodes.Bgt
			},
			{
				OpCodes.Bgt_Un_S,
				OpCodes.Bgt_Un
			},
			{
				OpCodes.Ble_S,
				OpCodes.Ble
			},
			{
				OpCodes.Ble_Un_S,
				OpCodes.Ble_Un
			},
			{
				OpCodes.Blt_S,
				OpCodes.Blt
			},
			{
				OpCodes.Blt_Un_S,
				OpCodes.Blt_Un
			},
			{
				OpCodes.Bne_Un_S,
				OpCodes.Bne_Un
			},
			{
				OpCodes.Brfalse_S,
				OpCodes.Brfalse
			},
			{
				OpCodes.Brtrue_S,
				OpCodes.Brtrue
			},
			{
				OpCodes.Br_S,
				OpCodes.Br
			},
			{
				OpCodes.Ldarg_S,
				OpCodes.Ldarg
			},
			{
				OpCodes.Ldarga_S,
				OpCodes.Ldarga
			},
			{
				OpCodes.Ldloc_S,
				OpCodes.Ldloc
			},
			{
				OpCodes.Ldloca_S,
				OpCodes.Ldloca
			},
			{
				OpCodes.Leave_S,
				OpCodes.Leave
			},
			{
				OpCodes.Starg_S,
				OpCodes.Starg
			},
			{
				OpCodes.Stloc_S,
				OpCodes.Stloc
			}
		};

		private static Dictionary<OpCode, OpCode> UltraSimplifyDict = new Dictionary<OpCode, OpCode>
		{
			{
				OpCodes.Beq_S,
				OpCodes.Beq
			},
			{
				OpCodes.Bge_S,
				OpCodes.Bge
			},
			{
				OpCodes.Bge_Un_S,
				OpCodes.Bge_Un
			},
			{
				OpCodes.Bgt_S,
				OpCodes.Bgt
			},
			{
				OpCodes.Bgt_Un_S,
				OpCodes.Bgt_Un
			},
			{
				OpCodes.Ble_S,
				OpCodes.Ble
			},
			{
				OpCodes.Ble_Un_S,
				OpCodes.Ble_Un
			},
			{
				OpCodes.Blt_S,
				OpCodes.Blt
			},
			{
				OpCodes.Blt_Un_S,
				OpCodes.Blt_Un
			},
			{
				OpCodes.Bne_Un_S,
				OpCodes.Bne_Un
			},
			{
				OpCodes.Brfalse_S,
				OpCodes.Brfalse
			},
			{
				OpCodes.Brtrue_S,
				OpCodes.Brtrue
			},
			{
				OpCodes.Br_S,
				OpCodes.Br
			},
			{
				OpCodes.Ldarga_S,
				OpCodes.Ldarga
			},
			{
				OpCodes.Ldarg_0,
				OpCodes.Ldarg
			},
			{
				OpCodes.Ldarg_1,
				OpCodes.Ldarg
			},
			{
				OpCodes.Ldarg_2,
				OpCodes.Ldarg
			},
			{
				OpCodes.Ldarg_3,
				OpCodes.Ldarg
			},
			{
				OpCodes.Ldloca_S,
				OpCodes.Ldloca
			},
			{
				OpCodes.Ldloc_S,
				OpCodes.Ldloc
			},
			{
				OpCodes.Ldloc_0,
				OpCodes.Ldloc
			},
			{
				OpCodes.Ldloc_1,
				OpCodes.Ldloc
			},
			{
				OpCodes.Ldloc_2,
				OpCodes.Ldloc
			},
			{
				OpCodes.Ldloc_3,
				OpCodes.Ldloc
			},
			{
				OpCodes.Leave_S,
				OpCodes.Leave
			},
			{
				OpCodes.Starg_S,
				OpCodes.Starg
			},
			{
				OpCodes.Stloc_S,
				OpCodes.Stloc
			},
			{
				OpCodes.Stloc_0,
				OpCodes.Stloc
			},
			{
				OpCodes.Stloc_1,
				OpCodes.Stloc
			},
			{
				OpCodes.Stloc_2,
				OpCodes.Stloc
			},
			{
				OpCodes.Stloc_3,
				OpCodes.Stloc
			},
			{
				OpCodes.Ldc_I4_0,
				OpCodes.Ldc_I4
			},
			{
				OpCodes.Ldc_I4_1,
				OpCodes.Ldc_I4
			},
			{
				OpCodes.Ldc_I4_2,
				OpCodes.Ldc_I4
			},
			{
				OpCodes.Ldc_I4_3,
				OpCodes.Ldc_I4
			},
			{
				OpCodes.Ldc_I4_4,
				OpCodes.Ldc_I4
			},
			{
				OpCodes.Ldc_I4_5,
				OpCodes.Ldc_I4
			},
			{
				OpCodes.Ldc_I4_6,
				OpCodes.Ldc_I4
			},
			{
				OpCodes.Ldc_I4_7,
				OpCodes.Ldc_I4
			},
			{
				OpCodes.Ldc_I4_8,
				OpCodes.Ldc_I4
			}
		};

		private static OpCode Simplify(OpCode op, bool ultra = false)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			if (ultra && UltraSimplifyDict.ContainsKey(op))
			{
				return UltraSimplifyDict[op];
			}
			if (SimplifyDict.ContainsKey(op))
			{
				return SimplifyDict[op];
			}
			return op;
		}

		public static bool LooseEquals(this OpCode op1, OpCode op2, bool ultra = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			return Simplify(op1, ultra) == Simplify(op2, ultra);
		}

		public static int SearchFor(this Collection<Instruction> collection, OpCode[] opCodes, int startIndex = 0, bool ultraSimplify = false)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			for (int i = startIndex; i < collection.Count - opCodes.Length; i++)
			{
				Instruction val = collection[i];
				if (val.OpCode.LooseEquals(opCodes[num]))
				{
					num++;
					if (num == opCodes.Length)
					{
						return i - opCodes.Length + 1;
					}
				}
				else
				{
					num = 0;
				}
			}
			return -1;
		}
	}
}