Decompiled source of MoreHeadUtilities v1.0.7

MoreHeadUtilities.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using MenuLib;
using MenuLib.MonoBehaviors;
using Microsoft.CodeAnalysis;
using MoreHead;
using MoreHead.MoreHead.Patchers;
using MoreHeadUtilities.Plugin;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("MoreHeadUtilities")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+3911decbf9634d63ae1bca5173060ee0fee13c40")]
[assembly: AssemblyProduct("MoreHeadUtilities")]
[assembly: AssemblyTitle("MoreHeadUtilities")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 MoreHeadUtilities
{
	public class PartShrinker : MonoBehaviour
	{
		[SerializeField]
		private HiddenParts.Part partToHide = HiddenParts.Part.LeftPupil;

		[SerializeField]
		private bool hideChildren = true;

		private Transform TotalParent;

		private HiddenParts parentComponent;

		private static double totalSearchingTime;

		private bool isFrameOne = true;

		private bool isFrameTwo;

		public static ManualLogSource bepInExLog;

		public static void Init(ManualLogSource source)
		{
			bepInExLog = source;
			bepInExLog.LogInfo((object)"LoggerUtil initialized!");
		}

		public void Log(string message)
		{
			if (MoreHeadUtilitiesPlugin._enableDebugLogging.Value)
			{
				bepInExLog.LogInfo((object)message);
			}
		}

		public void LogError(string message)
		{
			if (MoreHeadUtilitiesPlugin._enableDebugLogging.Value)
			{
				bepInExLog.LogError((object)message);
			}
		}

		public void Update()
		{
			if (isFrameOne)
			{
				isFrameOne = false;
				isFrameTwo = true;
			}
			else
			{
				if (!isFrameTwo)
				{
					return;
				}
				isFrameTwo = false;
				Stopwatch.StartNew();
				if (!Object.op_Implicit((Object)(object)parentComponent))
				{
					Log(((Object)((Component)this).gameObject).name + " is finding parent on awakening");
					TotalParent = ((Component)this).transform;
					while (((Object)TotalParent).name != "ANIM BOT" && ((Object)TotalParent).name != null && ((Object)TotalParent).name != "WorldDecorationFollower")
					{
						TotalParent = TotalParent.parent;
					}
					if (((Object)TotalParent).name == null)
					{
						LogError("No root found");
						return;
					}
					if (((Object)TotalParent).name == "WorldDecorationFollower")
					{
						LogError(((Object)((Component)this).gameObject).name + " is set to world parent. MoreHeadUtilities does not support part removal from a world object.");
						return;
					}
					parentComponent = ((Component)TotalParent).GetComponent<HiddenParts>();
					if (!Object.op_Implicit((Object)(object)parentComponent))
					{
						parentComponent = ((Component)TotalParent).gameObject.AddComponent<HiddenParts>();
					}
					else
					{
						Log("Part already exists");
					}
				}
				parentComponent.AddHiddenPart(partToHide, hideChildren);
			}
		}

		private void OnDisable()
		{
			if (isFrameOne)
			{
				return;
			}
			isFrameOne = true;
			if (!Object.op_Implicit((Object)(object)parentComponent))
			{
				Log(((Object)((Component)this).gameObject).name + " is finding parent for destruction");
				TotalParent = ((Component)this).transform;
				while (((Object)TotalParent).name != "ANIM BOT" && ((Object)TotalParent).name != null && ((Object)TotalParent).name != "WorldDecorationFollower")
				{
					TotalParent = TotalParent.parent;
				}
				if (((Object)TotalParent).name == null)
				{
					LogError("No root found");
					return;
				}
				if (((Object)TotalParent).name == "WorldDecorationFollower")
				{
					LogError(((Object)((Component)this).gameObject).name + " is set to world parent. MoreHeadUtilities does not support part removal from a world object.");
					return;
				}
				parentComponent = ((Component)TotalParent).GetComponent<HiddenParts>();
				if (!Object.op_Implicit((Object)(object)parentComponent))
				{
					parentComponent = ((Component)TotalParent).gameObject.AddComponent<HiddenParts>();
				}
				else
				{
					Log("Component already exists");
				}
			}
			parentComponent.RemoveHiddenPart(partToHide, hideChildren);
		}
	}
	public class HiddenParts : MonoBehaviour
	{
		public enum Part
		{
			Health,
			LeftArm,
			RightArm,
			LeftLeg,
			RightLeg,
			EyeLeft,
			EyeRight,
			Head,
			Neck,
			Body,
			Hips,
			LeftPupil,
			RightPupil
		}

		public static ManualLogSource bepInExLog;

		private string[][] partNames = new string[13][]
		{
			new string[3] { "mesh_health", "mesh_health frame", "mesh_health shadow" },
			new string[1] { "mesh_arm_l" },
			new string[1] { "mesh_arm_r" },
			new string[1] { "mesh_leg_l" },
			new string[1] { "mesh_leg_r" },
			new string[1] { "mesh_eye_l" },
			new string[1] { "mesh_eye_r" },
			new string[1] { "mesh_head_top" },
			new string[2] { "mesh_head_bot_sphere", "mesh_head_bot_flat" },
			new string[2] { "mesh_body_top_sphere", "mesh_body_top_flat" },
			new string[1] { "mesh_body_bot" },
			new string[1] { "mesh_pupil_l" },
			new string[1] { "mesh_pupil_r" }
		};

		private MeshRenderer[][] partRenderers = new MeshRenderer[13][]
		{
			(MeshRenderer[])(object)new MeshRenderer[3],
			(MeshRenderer[])(object)new MeshRenderer[1],
			(MeshRenderer[])(object)new MeshRenderer[1],
			(MeshRenderer[])(object)new MeshRenderer[1],
			(MeshRenderer[])(object)new MeshRenderer[1],
			(MeshRenderer[])(object)new MeshRenderer[1],
			(MeshRenderer[])(object)new MeshRenderer[1],
			(MeshRenderer[])(object)new MeshRenderer[1],
			(MeshRenderer[])(object)new MeshRenderer[2],
			(MeshRenderer[])(object)new MeshRenderer[2],
			(MeshRenderer[])(object)new MeshRenderer[1],
			(MeshRenderer[])(object)new MeshRenderer[1],
			(MeshRenderer[])(object)new MeshRenderer[1]
		};

		private Part[][] childParts = new Part[13][]
		{
			new Part[0],
			new Part[0],
			new Part[0],
			new Part[0],
			new Part[0],
			new Part[1] { Part.LeftPupil },
			new Part[1] { Part.RightPupil },
			new Part[2]
			{
				Part.EyeLeft,
				Part.EyeRight
			},
			new Part[2]
			{
				Part.Head,
				Part.Health
			},
			new Part[3]
			{
				Part.Neck,
				Part.LeftArm,
				Part.RightArm
			},
			new Part[3]
			{
				Part.Body,
				Part.LeftLeg,
				Part.RightLeg
			},
			new Part[0],
			new Part[0]
		};

		private List<Part> hiddenParts = new List<Part>();

		private bool updatedThisFrame;

		public static void Init(ManualLogSource source)
		{
			bepInExLog = source;
			bepInExLog.LogInfo((object)"LoggerUtil initialized!");
		}

		public void Log(string message)
		{
			ManualLogSource obj = bepInExLog;
			if (obj != null)
			{
				obj.LogInfo((object)message);
			}
		}

		public void LogError(string message)
		{
			ManualLogSource obj = bepInExLog;
			if (obj != null)
			{
				obj.LogError((object)message);
			}
		}

		public void Start()
		{
			foreach (Part value in Enum.GetValues(typeof(Part)))
			{
				for (int i = 0; i < partNames[(int)value].Length; i++)
				{
					Transform val = FindInHierarchy(((Component)this).transform, partNames[(int)value][i]);
					if ((Object)(object)val == (Object)null)
					{
						Log("Part '" + partNames[(int)value][i] + "' not found");
						continue;
					}
					MeshRenderer component = ((Component)val).gameObject.GetComponent<MeshRenderer>();
					if (Object.op_Implicit((Object)(object)component))
					{
						Log("Found part '" + partNames[(int)value][i] + "'");
						partRenderers[(int)value][i] = component;
					}
				}
			}
		}

		public void AddHiddenPart(Part part, bool hideChildren, bool update = true)
		{
			Log($"Adding part {part}");
			hiddenParts.Add(part);
			if (hideChildren)
			{
				Part[] array = childParts[(int)part];
				foreach (Part part2 in array)
				{
					AddHiddenPart(part2, hideChildren, update: false);
				}
			}
			updatedThisFrame = true;
		}

		public void RemoveHiddenPart(Part part, bool hideChildren, bool update = true)
		{
			if (hiddenParts.Contains(part))
			{
				hiddenParts.Remove(part);
			}
			if (hideChildren)
			{
				Part[] array = childParts[(int)part];
				foreach (Part part2 in array)
				{
					RemoveHiddenPart(part2, hideChildren, update: false);
				}
			}
			updatedThisFrame = true;
		}

		private Transform FindInHierarchy(Transform parent, string name)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			if (((Object)parent).name == name)
			{
				return parent;
			}
			foreach (Transform item in parent)
			{
				Transform parent2 = item;
				Transform val = FindInHierarchy(parent2, name);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		public void LateUpdate()
		{
			if (updatedThisFrame)
			{
				UpdateHiddenParts();
				updatedThisFrame = false;
			}
		}

		public void UpdateHiddenParts()
		{
			Log($"Updating parts, to be hidden: {hiddenParts.ToArray()}");
			foreach (Part value in Enum.GetValues(typeof(Part)))
			{
				ShowPart(value);
			}
			foreach (Part hiddenPart in hiddenParts)
			{
				HidePart(hiddenPart);
			}
		}

		private void ShowPart(Part partToShow)
		{
			for (int i = 0; i < partNames[(int)partToShow].Length; i++)
			{
				MeshRenderer component = ((Component)partRenderers[(int)partToShow][i]).gameObject.GetComponent<MeshRenderer>();
				if (Object.op_Implicit((Object)(object)component))
				{
					((Renderer)component).enabled = true;
				}
			}
		}

		private void HidePart(Part partToHide)
		{
			for (int i = 0; i < partNames[(int)partToHide].Length; i++)
			{
				MeshRenderer component = ((Component)partRenderers[(int)partToHide][i]).gameObject.GetComponent<MeshRenderer>();
				if (Object.op_Implicit((Object)(object)component))
				{
					((Renderer)component).enabled = false;
				}
			}
		}
	}
}
namespace MoreHeadUtilities.Plugin
{
	[BepInPlugin("com.maygik.moreheadutilities", "MoreHeadUtilities", "1.0.0")]
	public class MoreHeadUtilitiesPlugin : BaseUnityPlugin
	{
		public static ConfigEntry<bool> _enableDebugLogging;

		private void Awake()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			_enableDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableDebugLogging", false, "Enable debug logging for MoreHeadUtilities.");
			if (_enableDebugLogging.Value)
			{
				PartShrinker.Init(((BaseUnityPlugin)this).Logger);
				ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
				if (logger != null)
				{
					logger.LogInfo((object)"MoreHeadUtilities initialized and logger passed to PartShrinker.");
				}
				HiddenParts.Init(((BaseUnityPlugin)this).Logger);
				ManualLogSource logger2 = ((BaseUnityPlugin)this).Logger;
				if (logger2 != null)
				{
					logger2.LogInfo((object)"MoreHeadUtilities initialized and logger passed to HiddenParts.");
				}
				Logger.Init(((BaseUnityPlugin)this).Logger);
				ManualLogSource logger3 = ((BaseUnityPlugin)this).Logger;
				if (logger3 != null)
				{
					logger3.LogInfo((object)"MoreHeadUtilities initialized and logger passed to DecorationGroups.");
				}
			}
			new Harmony("com.maygik.moreheadutilities").PatchAll();
			ManualLogSource logger4 = ((BaseUnityPlugin)this).Logger;
			if (logger4 != null)
			{
				logger4.LogInfo((object)"Harmony patches applied.");
			}
		}
	}
}
namespace MoreHead
{
	internal static class Logger
	{
		public static ManualLogSource? log;

		public static void Init(ManualLogSource logger)
		{
			log = logger;
		}

		public static void Log(string message)
		{
			ManualLogSource? obj = log;
			if (obj != null)
			{
				obj.LogInfo((object)message);
			}
		}

		public static void LogError(string message)
		{
			ManualLogSource? obj = log;
			if (obj != null)
			{
				obj.LogError((object)message);
			}
		}
	}
	internal static class MoreHeadGroupStorage
	{
		public static Dictionary<string?, List<string?>> tagGroupElements = new Dictionary<string, List<string>>();

		public static Dictionary<string, bool> activeGroups = new Dictionary<string, bool>();
	}
	internal static class MoreHeadUIStorage
	{
		[CanBeNull]
		public static REPOPopupPage page = null;

		[CanBeNull]
		public static string group = null;

		public static bool resetPosition = true;

		public static Dictionary<string?, REPOButton> groupButtons = new Dictionary<string, REPOButton>();

		public static Dictionary<string?, List<string>> groupButtonTags = new Dictionary<string, List<string>>();
	}
	internal class HeadDecorationManagerStorage
	{
		public static List<string?> Decorations = new List<string>();
	}
	[HarmonyPatch(typeof(MoreHeadUI))]
	[HarmonyPatch("CreateAllDecorationButtons", new Type[] { typeof(REPOPopupPage) })]
	internal static class Patch_CreateAllDecorationButtons
	{
		private static readonly MethodInfo ClearScrolls = AccessTools.Method(typeof(Dictionary<string, List<REPOScrollViewElement>>), "Clear", (Type[])null, (Type[])null);

		private static readonly MethodInfo ToListDecorations = AccessTools.Method(typeof(Enumerable), "ToList", (Type[])null, (Type[])null).MakeGenericMethod(typeof(DecorationInfo));

		private static readonly MethodInfo Helper1 = AccessTools.Method(typeof(MoreHeadUIHelpers), "Patch1_CreateAllDecorationButtons", (Type[])null, (Type[])null);

		private static readonly MethodInfo Helper2 = AccessTools.Method(typeof(MoreHeadUIHelpers), "Patch2_CreateAllDecorationButtons", new Type[1] { typeof(REPOPopupPage) }, (Type[])null);

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instrs, ILGenerator il)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Expected O, but got Unknown
			List<CodeInstruction> list = instrs.ToList();
			bool flag = false;
			bool flag2 = false;
			for (int i = 0; i < list.Count; i++)
			{
				CodeInstruction val = list[i];
				if (!flag && val.opcode == OpCodes.Callvirt && val.operand == ClearScrolls)
				{
					Logger.Log("Patching Patch1_CreateAllDecorationButtons");
					list.Insert(++i, new CodeInstruction(OpCodes.Call, (object)Helper1));
					flag = true;
				}
				else if (!flag2 && val.opcode == OpCodes.Call && val.operand == ToListDecorations)
				{
					Logger.Log("Patching Patch2_CreateAllDecorationButtons");
					int num = list.FindLastIndex((CodeInstruction ci) => ci.opcode == OpCodes.Ret);
					if (num < 0)
					{
						throw new InvalidOperationException("Couldn't find the final ret in CreateAllDecorationButtons");
					}
					CodeInstruction obj = list[num];
					Label label = il.DefineLabel();
					obj.labels.Add(label);
					list.Insert(++i, new CodeInstruction(OpCodes.Ldarg_0, (object)null));
					list.Insert(++i, new CodeInstruction(OpCodes.Call, (object)Helper2));
					list.Insert(++i, new CodeInstruction(OpCodes.Leave_S, (object)label));
					Logger.Log("Patched Patch2_CreateAllDecorationButtons");
					break;
				}
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(MoreHeadUI))]
	[HarmonyPatch("CreateAllDecorationButtons", new Type[] { typeof(REPOPopupPage) })]
	internal static class Prefix_CreateAllDecorationButtons
	{
		[HarmonyPrefix]
		private static bool Prefix(REPOPopupPage page)
		{
			MoreHeadUIStorage.page = page;
			MoreHeadUIStorage.groupButtons.Clear();
			MoreHeadUIStorage.groupButtonTags.Clear();
			return true;
		}
	}
	[HarmonyPatch(typeof(MoreHeadUI))]
	[HarmonyPatch("CreateDecorationButton", new Type[]
	{
		typeof(REPOPopupPage),
		typeof(DecorationInfo)
	})]
	internal static class Patch_CreateDecorationButton
	{
		private static readonly MethodInfo ShowTagDecorationsMI = AccessTools.Method(typeof(MoreHeadUI), "ShowTagDecorations", new Type[1] { typeof(string) }, (Type[])null);

		[HarmonyPrefix]
		private static bool Prefix(REPOPopupPage page, DecorationInfo decoration)
		{
			try
			{
				string text = HeadDecorationManagerStorage.Decorations[HeadDecorationManager.Decorations.IndexOf(decoration)];
				if (text != null && text != "" && MoreHeadGroupStorage.tagGroupElements.TryGetValue("ALL", out List<string> value))
				{
					if (!MoreHeadGroupStorage.activeGroups.ContainsKey(text))
					{
						Logger.Log("Initialising group: " + text);
						MoreHeadGroupStorage.activeGroups[text] = false;
					}
					if (!value.Contains(text))
					{
						CreateGroupButton(page, text);
					}
				}
				string[] source = (string[])typeof(MoreHeadUI).GetField("LIMB_TAGS", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null);
				MoreHeadGroupStorage.tagGroupElements["ALL"].Add(text);
				if (text != null)
				{
					if (!MoreHeadUIStorage.groupButtonTags.ContainsKey(text))
					{
						Logger.Log("Initialising group button tag list for " + text);
						MoreHeadUIStorage.groupButtonTags[text] = new List<string>();
					}
					MoreHeadUIStorage.groupButtonTags[text].Add("ALL");
				}
				List<string> value2;
				if (source.Contains(decoration.ParentTag.ToUpper()))
				{
					MoreHeadGroupStorage.tagGroupElements["LIMBS"].Add(text);
					if (text != null)
					{
						MoreHeadUIStorage.groupButtonTags[text].Add("LIMBS");
					}
				}
				else if (MoreHeadGroupStorage.tagGroupElements.TryGetValue(decoration.ParentTag.ToUpper(), out value2))
				{
					value2.Add(text);
					if (text != null)
					{
						MoreHeadUIStorage.groupButtonTags[text].Add(decoration.ParentTag.ToUpper());
					}
				}
				return true;
			}
			catch (Exception arg)
			{
				Logger.LogError($"Error creating decoration button {decoration.Name}: {arg}");
				throw;
			}
		}

		private static string GetGroupButtonText(string group)
		{
			if (!MoreHeadGroupStorage.activeGroups[group])
			{
				return "<size=20><color=#CCCCCC>[+]" + group + "</color></size>";
			}
			return "<size=20><color=#777777>[-]" + group + "</color></size>";
		}

		private static void CreateGroupButton(REPOPopupPage page, string groupName)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			Logger.Log("Creating group button: " + groupName);
			try
			{
				string buttonText = GetGroupButtonText(groupName);
				REPOButton repoButton = null;
				page.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView)
				{
					//IL_0038: 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)
					repoButton = MenuAPI.CreateREPOButton(buttonText, (Action)delegate
					{
						OnDecorationGroupButtonClick(groupName);
					}, scrollView, default(Vector2));
					return ((REPOElement)repoButton).rectTransform;
				}, 0f, 0f);
				if ((Object)(object)repoButton != (Object)null)
				{
					MoreHeadUIStorage.groupButtons[groupName] = repoButton;
					MoreHeadUIStorage.groupButtonTags[groupName] = new List<string>();
					MoreHeadUIStorage.group = groupName;
					Logger.Log("Created group button: " + groupName);
					return;
				}
				throw new Exception("Failed to create group button.");
			}
			catch (Exception ex)
			{
				Logger.Log("Error creating group button: " + ex.Message);
			}
		}

		private static void OnDecorationGroupButtonClick(string? groupName)
		{
			Logger.Log("OnDecorationGroupButtonClick called for group: " + groupName);
			MoreHeadGroupStorage.activeGroups[groupName] = !MoreHeadGroupStorage.activeGroups[groupName];
			Logger.Log("Invoking show tag decorations");
			string text = (string)typeof(MoreHeadUI).GetField("currentTagFilter", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
			MoreHeadUIStorage.resetPosition = false;
			ShowTagDecorationsMI.Invoke(null, new object[1] { text });
			if (MoreHeadUIStorage.groupButtons.TryGetValue(groupName, out var value))
			{
				string groupButtonText = GetGroupButtonText(groupName);
				((TMP_Text)value.labelTMP).text = groupButtonText;
			}
			MoreHeadUIStorage.resetPosition = true;
		}
	}
	[HarmonyPatch(typeof(HeadDecorationManager))]
	[HarmonyPatch("LoadDecorationBundle", new Type[] { typeof(string) })]
	internal static class Patch_LoadDecorationBundle
	{
		private static readonly MethodInfo EnsureUniqueDisplayName = AccessTools.Method(typeof(HeadDecorationManager), "EnsureUniqueDisplayName", new Type[1] { typeof(string) }, (Type[])null);

		private static readonly MethodInfo EnsureUniqueName = AccessTools.Method(typeof(HeadDecorationManager), "EnsureUniqueName", new Type[1] { typeof(string) }, (Type[])null);

		private static readonly MethodInfo AddDecorationHelper1 = AccessTools.Method(typeof(HeadDecorationManagerHelpers), "Patch1_LoadDecorationBundle", new Type[1] { typeof(string) }, (Type[])null);

		private static readonly MethodInfo AddDecorationHelper2 = AccessTools.Method(typeof(HeadDecorationManagerHelpers), "Patch2_LoadDecorationBundle", (Type[])null, (Type[])null);

		private static readonly MethodInfo AddDecorationHelper3 = AccessTools.Method(typeof(HeadDecorationManagerHelpers), "Patch3_LoadDecorationBundle", (Type[])null, (Type[])null);

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instrs)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			List<CodeInstruction> list = instrs.ToList();
			bool flag = false;
			bool flag2 = false;
			bool flag3 = false;
			for (int i = 0; i < list.Count(); i++)
			{
				CodeInstruction val = list[i];
				if (val.opcode == OpCodes.Call && val.operand == EnsureUniqueDisplayName)
				{
					Logger.Log("Patching AddDecorationHelper2");
					list.Insert(i, new CodeInstruction(OpCodes.Call, (object)AddDecorationHelper2));
					Logger.Log("Patched AddDecorationHelper2");
					flag2 = true;
					i += 2;
				}
				if (val.opcode == OpCodes.Call && val.operand == EnsureUniqueName)
				{
					Logger.Log("Patching AddDecorationHelper1");
					list.Insert(i, new CodeInstruction(OpCodes.Dup, (object)null));
					list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)AddDecorationHelper1));
					Logger.Log("Patched AddDecorationHelper1");
					flag = true;
					i += 2;
				}
				if (!flag3 && list[i].opcode == OpCodes.Call && list[i].operand == AccessTools.Method(typeof(DecorationBlacklistManager), "IsBlacklisted", new Type[1] { typeof(string) }, (Type[])null))
				{
					int num = i + 4;
					Logger.Log("Patching AddDecorationHelper3");
					list.Insert(num++, new CodeInstruction(OpCodes.Call, (object)AddDecorationHelper3));
					Logger.Log("Patched AddDecorationHelper3");
					flag3 = true;
					i += 5;
				}
				if (flag2 && flag && flag3)
				{
					break;
				}
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(MoreHeadUI))]
	[HarmonyPatch("CreateDecorationButton", new Type[]
	{
		typeof(REPOPopupPage),
		typeof(DecorationInfo)
	})]
	internal static class Transpiler_CreateDecorationButton
	{
		private static readonly MethodInfo PatchMethod = AccessTools.Method(typeof(MoreHeadUIHelpers), "Patch1_CreateDecorationButton", new Type[2]
		{
			typeof(DecorationInfo),
			typeof(string)
		}, (Type[])null);

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instrs)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			List<CodeInstruction> list = instrs.ToList();
			for (int i = 0; i < list.Count; i++)
			{
				CodeInstruction val = list[i];
				if (val.opcode == OpCodes.Callvirt && val.operand is MethodInfo methodInfo && methodInfo.Name == "Add" && methodInfo.DeclaringType == typeof(List<REPOScrollViewElement>))
				{
					Logger.Log("Patch adding group");
					list.Insert(i + 1, new CodeInstruction(OpCodes.Ldarg_1, (object)null));
					list.Insert(i + 2, new CodeInstruction(OpCodes.Ldstr, (object)(MoreHeadUIStorage.group ?? "")));
					list.Insert(i + 3, new CodeInstruction(OpCodes.Call, (object)PatchMethod));
					i += 3;
				}
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(MoreHeadUI))]
	[HarmonyPatch("ShowTagDecorations", new Type[] { typeof(string) })]
	internal static class Patch_ShowTagDecorations
	{
		[HarmonyPrefix]
		private static bool Prefix(string tag)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			try
			{
				Type typeFromHandle = typeof(MoreHeadUI);
				Logger.Log("Accessing decorationsPage");
				REPOPopupPage val = (REPOPopupPage)typeFromHandle.GetField("decorationsPage", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null);
				Logger.Log("Accessing tagScrollViewElements");
				Dictionary<string, List<REPOScrollViewElement>> dictionary = (Dictionary<string, List<REPOScrollViewElement>>)typeFromHandle.GetField("tagScrollViewElements", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null);
				Logger.Log("Accessing currentTagFilter");
				FieldInfo field = typeFromHandle.GetField("currentTagFilter", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				string text = (string)field.GetValue(null);
				Logger.Log("Running the proper ShowTagDecorations function");
				dictionary.TryGetValue(text, out var value);
				MoreHeadGroupStorage.tagGroupElements.TryGetValue(text, out List<string> value2);
				Logger.Log($"There are {value.Count()} scroll elements and {value2.Count()} grouped elements");
				if (!string.IsNullOrEmpty(text))
				{
					for (int i = 0; i < value.Count(); i++)
					{
						if ((Object)(object)value[i] != (Object)null)
						{
							value[i].visibility = false;
						}
					}
					for (int j = 0; j < value2.Count(); j++)
					{
						if (value2[j] != null)
						{
							((REPOElement)MoreHeadUIStorage.groupButtons[value2[j]]).repoScrollViewElement.visibility = false;
						}
					}
				}
				Logger.Log("Element visibility hidden");
				dictionary.TryGetValue(tag, out value);
				MoreHeadGroupStorage.tagGroupElements.TryGetValue(tag, out value2);
				Logger.Log($"There are {value.Count()} tagged scroll elements and {value2.Count()} tagged grouped elements");
				if (!string.IsNullOrEmpty(tag))
				{
					for (int k = 0; k < value.Count(); k++)
					{
						if (value2[k] == null)
						{
							if ((Object)(object)value[k] != (Object)null)
							{
								value[k].visibility = true;
							}
						}
						else if ((Object)(object)value[k] != (Object)null && MoreHeadGroupStorage.activeGroups[value2[k]])
						{
							value[k].visibility = true;
						}
					}
					for (int l = 0; l < value2.Count(); l++)
					{
						if (value2[l] != null && MoreHeadUIStorage.groupButtonTags[value2[l]].Contains(tag))
						{
							((REPOElement)MoreHeadUIStorage.groupButtons[value2[l]]).repoScrollViewElement.visibility = true;
						}
					}
				}
				field.SetValue(null, tag);
				if (MoreHeadUIStorage.resetPosition)
				{
					val.scrollView.SetScrollPosition(0f);
				}
				val.scrollView.UpdateElements();
			}
			catch (Exception ex)
			{
				Logger.LogError("Error showing decorations for tag: " + tag + " | Error: " + ex.Message);
			}
			return false;
		}
	}
}
namespace MoreHead.MoreHead.Patchers
{
	public static class HeadDecorationManagerHelpers
	{
		public static string bundleName;

		public static void Patch1_LoadDecorationBundle(string bundleBaseName)
		{
			Logger.Log("Saving bundle name");
			bundleName = bundleBaseName;
		}

		public static void Patch2_LoadDecorationBundle()
		{
			Logger.Log("Patch_LoadDecorationBundle called");
			string text = null;
			if (bundleName.Contains("~"))
			{
				string[] array = bundleName.Split(new char[1] { '~' });
				if (array.Length >= 2)
				{
					text = array[^1].ToLower();
					Logger.Log("Setting group: " + text);
				}
			}
			Logger.Log("Adding decoration");
			HeadDecorationManagerStorage.Decorations.Add(text);
		}

		public static void Patch3_LoadDecorationBundle()
		{
			HeadDecorationManagerStorage.Decorations.RemoveAt(HeadDecorationManagerStorage.Decorations.Count - 1);
			Logger.Log("Removing last from decoration group list");
		}
	}
	public static class MoreHeadUIHelpers
	{
		private static bool _inHelper;

		public static void Patch1_CreateAllDecorationButtons()
		{
			Logger.Log("Starting patch of CreateAllDecorationButtons");
			Logger.Log("Accessing type MoreHeadUI");
			Type typeFromHandle = typeof(MoreHeadUI);
			Logger.Log("Setting binding flags to Static and NonPublic");
			Logger.Log("Retrieving ALL_TAGS field from MoreHeadUI");
			string[] array = (string[])typeFromHandle.GetField("ALL_TAGS", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
			foreach (string key in array)
			{
				MoreHeadGroupStorage.tagGroupElements[key] = new List<string>();
			}
		}

		public static void Patch2_CreateAllDecorationButtons(REPOPopupPage page)
		{
			try
			{
				Logger.Log("Starting Patch2_CreateAllDecorationButtons");
				_ = (string[])typeof(MoreHeadUI).GetField("ALL_TAGS", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
				List<DecorationInfo> allDecorations = HeadDecorationManager.Decorations.ToList();
				Logger.Log("Gotten IsBuiltInDecoration");
				MethodInfo isBuiltInMI = AccessTools.Method(typeof(MoreHeadUI), "IsBuiltInDecoration", new Type[1] { typeof(DecorationInfo) }, (Type[])null);
				if (isBuiltInMI.GetParameters().Length == 1 && isBuiltInMI.ReturnType == typeof(bool))
				{
					_ = (Func<DecorationInfo, bool>)Delegate.CreateDelegate(typeof(Func<DecorationInfo, bool>), isBuiltInMI);
					Logger.Log("Delegate successfully created for IsBuiltInDecoration.");
					Logger.Log("Bound Delegate");
					List<DecorationInfo> list = (from decoration in allDecorations
						where (bool)isBuiltInMI.Invoke(null, new object[1] { decoration })
						orderby HeadDecorationManagerStorage.Decorations[allDecorations.IndexOf(decoration)], decoration.DisplayName
						select decoration).ToList();
					Logger.Log("builtInDecorations sorted");
					List<DecorationInfo> list2 = (from decoration in allDecorations
						where !(bool)isBuiltInMI.Invoke(null, new object[1] { decoration })
						orderby HeadDecorationManagerStorage.Decorations[allDecorations.IndexOf(decoration)] ?? '\uffff'.ToString(), decoration.DisplayName
						select decoration).ToList();
					Logger.Log("externalDecorations sorted");
					MethodInfo methodInfo = AccessTools.Method(typeof(MoreHeadUI), "CreateDecorationButton", new Type[2]
					{
						typeof(REPOPopupPage),
						typeof(DecorationInfo)
					}, (Type[])null);
					foreach (DecorationInfo item in list)
					{
						methodInfo.Invoke(null, new object[2] { page, item });
					}
					foreach (DecorationInfo item2 in list2)
					{
						methodInfo.Invoke(null, new object[2] { page, item2 });
					}
					Logger.Log("externalDecorations all created");
					MoreHeadUIStorage.group = null;
					return;
				}
				throw new InvalidOperationException("IsBuiltInDecoration method signature does not match Func<DecorationInfo, bool>.");
			}
			catch (Exception arg)
			{
				Logger.LogError($"Error creating all decoration buttons: {arg}");
				throw;
			}
		}

		public static void Patch1_CreateDecorationButton(DecorationInfo decoration, string group)
		{
			if (_inHelper)
			{
				return;
			}
			_inHelper = true;
			try
			{
			}
			finally
			{
				_inHelper = false;
			}
		}
	}
}