Decompiled source of MoreHeadHoverFix v1.0.1

BepInEx/patchers/MoreHeadHoverFix/MoreHeadHoverFix.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx.Logging;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("1.0.1.0")]
namespace MoreHeadHoverFix;

public static class Patcher
{
	private static readonly ManualLogSource Log = Logger.CreateLogSource("MoreHeadHoverFix");

	public static IEnumerable<string> TargetDLLs
	{
		get
		{
			yield return "Assembly-CSharp.dll";
		}
	}

	public static void Patch(AssemblyDefinition assembly)
	{
		Restore(assembly, "MenuElementHover", "isHovering", "System.Boolean");
		Restore(assembly, "MenuSelectableElement", "menuID", "System.String");
	}

	private static void Restore(AssemblyDefinition assembly, string typeName, string name, string fieldType)
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		TypeDefinition type = assembly.MainModule.GetType(typeName);
		if (type == null)
		{
			Log.LogWarning((object)(typeName + " missing; skipping."));
			return;
		}
		string text = "<" + name + ">k__BackingField";
		FieldDefinition val = null;
		Enumerator<FieldDefinition> enumerator = type.Fields.GetEnumerator();
		try
		{
			while (enumerator.MoveNext())
			{
				FieldDefinition current = enumerator.Current;
				if (((MemberReference)current).Name == name)
				{
					Log.LogInfo((object)(typeName + "." + name + " already exists; skipping."));
					return;
				}
				if (((MemberReference)current).Name == text && ((MemberReference)((FieldReference)current).FieldType).FullName == fieldType && !current.IsStatic)
				{
					val = current;
				}
			}
		}
		finally
		{
			((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
		}
		PropertyDefinition val2 = null;
		Enumerator<PropertyDefinition> enumerator2 = type.Properties.GetEnumerator();
		try
		{
			while (enumerator2.MoveNext())
			{
				PropertyDefinition current2 = enumerator2.Current;
				if (((MemberReference)current2).Name == name && ((MemberReference)((PropertyReference)current2).PropertyType).FullName == fieldType)
				{
					val2 = current2;
				}
			}
		}
		finally
		{
			((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
		}
		if (val == null || val2 == null || val2.GetMethod == null || !val2.GetMethod.HasBody)
		{
			Log.LogWarning((object)("Unrecognized layout for " + typeName + "." + name + "; skipping."));
			return;
		}
		bool flag = false;
		Enumerator<Instruction> enumerator3 = val2.GetMethod.Body.Instructions.GetEnumerator();
		try
		{
			while (enumerator3.MoveNext())
			{
				Instruction current3 = enumerator3.Current;
				object operand = current3.Operand;
				FieldReference val3 = (FieldReference)((operand is FieldReference) ? operand : null);
				if (current3.OpCode == OpCodes.Ldfld && val3 != null && ((MemberReference)((MemberReference)val3).DeclaringType).FullName == typeName && ((MemberReference)val3).Name == text)
				{
					flag = true;
				}
			}
		}
		finally
		{
			((IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose();
		}
		if (!flag)
		{
			Log.LogWarning((object)("Getter storage changed for " + typeName + "." + name + "; skipping."));
			return;
		}
		List<FieldReference> list = new List<FieldReference>();
		Enumerator<TypeDefinition> enumerator4 = assembly.MainModule.Types.GetEnumerator();
		try
		{
			while (enumerator4.MoveNext())
			{
				TypeDefinition current4 = enumerator4.Current;
				Collect(current4, typeName, text, list);
			}
		}
		finally
		{
			((IDisposable)enumerator4/*cast due to .constrained prefix*/).Dispose();
		}
		((MemberReference)val).Name = name;
		foreach (FieldReference item in list)
		{
			((MemberReference)item).Name = name;
		}
		Log.LogInfo((object)("Restored " + typeName + "." + name + " field compatibility; property uses the same storage. Patched in memory only."));
	}

	private static void Collect(TypeDefinition type, string owner, string backingName, List<FieldReference> references)
	{
		//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)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		Enumerator<MethodDefinition> enumerator = type.Methods.GetEnumerator();
		try
		{
			while (enumerator.MoveNext())
			{
				MethodDefinition current = enumerator.Current;
				if (!current.HasBody)
				{
					continue;
				}
				Enumerator<Instruction> enumerator2 = current.Body.Instructions.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						Instruction current2 = enumerator2.Current;
						object operand = current2.Operand;
						FieldReference val = (FieldReference)((operand is FieldReference) ? operand : null);
						if (val != null && ((MemberReference)((MemberReference)val).DeclaringType).FullName == owner && ((MemberReference)val).Name == backingName)
						{
							references.Add(val);
						}
					}
				}
				finally
				{
					((IDisposable)enumerator2/*cast due to .constrained prefix*/).Dispose();
				}
			}
		}
		finally
		{
			((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
		}
		Enumerator<TypeDefinition> enumerator3 = type.NestedTypes.GetEnumerator();
		try
		{
			while (enumerator3.MoveNext())
			{
				TypeDefinition current3 = enumerator3.Current;
				Collect(current3, owner, backingName, references);
			}
		}
		finally
		{
			((IDisposable)enumerator3/*cast due to .constrained prefix*/).Dispose();
		}
	}
}