Decompiled source of ModSettingsMenu v2.0.3

BepInEx/plugins/ModSettingsMenu.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Sparroh.UI;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ModSettingsMenu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ModSettingsMenu")]
[assembly: AssemblyTitle("ModSettingsMenu")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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;
		}
	}
}
public static class FreeCursor
{
	private sealed class FreeCursorDriver : MonoBehaviour
	{
		private void Update()
		{
			Apply();
		}

		private void LateUpdate()
		{
			Apply();
		}

		private void OnApplicationFocus(bool hasFocus)
		{
			if (hasFocus)
			{
				Apply();
			}
		}
	}

	private static int _holders;

	private static bool _usedPlayerInput;

	private static FreeCursorDriver _driver;

	public static bool IsHeld => _holders > 0;

	public static void Acquire()
	{
		EnsureDriver();
		if (_holders == 0)
		{
			UnlockViaGame();
		}
		_holders++;
		Apply();
	}

	public static void Release()
	{
		if (_holders > 0)
		{
			_holders--;
			if (_holders == 0)
			{
				LockViaGame();
			}
		}
	}

	public static void Apply()
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		if (_holders > 0)
		{
			Cursor.lockState = PlayerInput.CursorMenuMode;
			Cursor.visible = true;
		}
	}

	private static void UnlockViaGame()
	{
		try
		{
			PlayerInput.UnlockCursor();
			_usedPlayerInput = true;
		}
		catch
		{
			_usedPlayerInput = false;
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}
	}

	private static void LockViaGame()
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		if (_usedPlayerInput)
		{
			try
			{
				PlayerInput.LockCursor();
			}
			catch
			{
			}
			finally
			{
				_usedPlayerInput = false;
			}
		}
		try
		{
			if (PlayerInput.IsMenuEnabled)
			{
				Cursor.lockState = PlayerInput.CursorMenuMode;
				Cursor.visible = true;
				return;
			}
		}
		catch
		{
		}
		try
		{
			if ((Object)(object)Menu.Instance != (Object)null && Menu.Instance.IsOpen)
			{
				Cursor.lockState = PlayerInput.CursorMenuMode;
				Cursor.visible = true;
			}
		}
		catch
		{
		}
	}

	private static void EnsureDriver()
	{
		//IL_0013: 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)
		//IL_001e: Expected O, but got Unknown
		if (!((Object)(object)_driver != (Object)null))
		{
			GameObject val = new GameObject("ModSettingsMenu_FreeCursor");
			Object.DontDestroyOnLoad((Object)val);
			_driver = val.AddComponent<FreeCursorDriver>();
		}
	}
}
public static class HudRepositionAPI
{
	public sealed class HudElement
	{
		public string Id { get; internal set; }

		public string DisplayName { get; internal set; }

		public RectTransform Rect { get; internal set; }

		public ConfigEntry<float> AnchorX { get; internal set; }

		public ConfigEntry<float> AnchorY { get; internal set; }

		public bool IsAutoDetected { get; internal set; }
	}

	private static readonly Dictionary<string, HudElement> Elements = new Dictionary<string, HudElement>(StringComparer.OrdinalIgnoreCase);

	public static bool IsRepositionModeActive => HudRepositionMode.IsActive;

	public static void Register(string id, string displayName, RectTransform rect, ConfigEntry<float> anchorX, ConfigEntry<float> anchorY)
	{
		if (string.IsNullOrEmpty(id))
		{
			throw new ArgumentException("id is required", "id");
		}
		if ((Object)(object)rect == (Object)null)
		{
			throw new ArgumentNullException("rect");
		}
		if (anchorX == null)
		{
			throw new ArgumentNullException("anchorX");
		}
		if (anchorY == null)
		{
			throw new ArgumentNullException("anchorY");
		}
		Elements[id] = new HudElement
		{
			Id = id,
			DisplayName = (string.IsNullOrEmpty(displayName) ? id : displayName),
			Rect = rect,
			AnchorX = anchorX,
			AnchorY = anchorY,
			IsAutoDetected = false
		};
		ManualLogSource logger = SparrohPlugin.Logger;
		if (logger != null)
		{
			logger.LogInfo((object)("[HudReposition] Registered '" + displayName + "' (" + id + ")"));
		}
	}

	public static void Unregister(string id)
	{
		if (!string.IsNullOrEmpty(id) && Elements.Remove(id))
		{
			ManualLogSource logger = SparrohPlugin.Logger;
			if (logger != null)
			{
				logger.LogInfo((object)("[HudReposition] Unregistered '" + id + "'"));
			}
		}
	}

	public static IReadOnlyList<HudElement> GetRegistered()
	{
		CleanupDestroyed();
		return Elements.Values.ToList();
	}

	public static void ToggleRepositionMode()
	{
		HudRepositionMode.Toggle();
	}

	public static void EnterRepositionMode()
	{
		HudRepositionMode.Enter();
	}

	public static void ExitRepositionMode()
	{
		HudRepositionMode.Exit();
	}

	internal static void RegisterAutoDetected(string id, string displayName, RectTransform rect, ConfigEntry<float> anchorX, ConfigEntry<float> anchorY)
	{
		if (!Elements.ContainsKey(id))
		{
			Elements[id] = new HudElement
			{
				Id = id,
				DisplayName = displayName,
				Rect = rect,
				AnchorX = anchorX,
				AnchorY = anchorY,
				IsAutoDetected = true
			};
		}
	}

	internal static void ClearAutoDetected()
	{
		foreach (string item in (from kv in Elements
			where kv.Value.IsAutoDetected
			select kv.Key).ToList())
		{
			Elements.Remove(item);
		}
	}

	internal static void CleanupDestroyed()
	{
		foreach (string item in (from kv in Elements
			where (Object)(object)kv.Value.Rect == (Object)null
			select kv.Key).ToList())
		{
			Elements.Remove(item);
		}
	}
}
public class HudRepositionMode : MonoBehaviour
{
	private sealed class AnchorPair
	{
		public string ConfigPath;

		public string Section;

		public string Prefix;

		public string KeyX;

		public string KeyY;

		public float DefaultX;

		public float DefaultY;
	}

	private HudRepositionAPI.HudElement _dragging;

	private Vector2 _dragGrabOffset;

	private bool _cursorHeld;

	private readonly Dictionary<string, ConfigFile> _autoConfigFiles = new Dictionary<string, ConfigFile>(StringComparer.OrdinalIgnoreCase);

	private static readonly Regex AnchorPairRegex = new Regex("^(?<prefix>.+)AnchorX$", RegexOptions.IgnoreCase | RegexOptions.Compiled);

	private const float MinHitWidth = 180f;

	private const float MinHitHeight = 36f;

	public static HudRepositionMode Instance { get; private set; }

	public static bool IsActive { get; private set; }

	public static void EnsureExists()
	{
		//IL_0013: 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)
		//IL_001e: Expected O, but got Unknown
		if (!((Object)(object)Instance != (Object)null))
		{
			GameObject val = new GameObject("HudRepositionMode");
			Object.DontDestroyOnLoad((Object)val);
			Instance = val.AddComponent<HudRepositionMode>();
		}
	}

	public static void Toggle()
	{
		EnsureExists();
		if (IsActive)
		{
			Exit();
		}
		else
		{
			Enter();
		}
	}

	public static void Enter()
	{
		EnsureExists();
		if (!IsActive)
		{
			IsActive = true;
			Instance.HoldCursor();
			Instance.RunAutoDetect();
			HudRepositionAPI.CleanupDestroyed();
			int count = HudRepositionAPI.GetRegistered().Count;
			SparrohPlugin.Logger.LogInfo((object)$"[HudReposition] Reposition mode ON — {count} element(s). Drag to move, Esc/F9 to exit.");
		}
	}

	public static void Exit()
	{
		if (!IsActive)
		{
			return;
		}
		if ((Object)(object)Instance != (Object)null)
		{
			if (Instance._dragging != null)
			{
				Instance.CommitDrag(Instance._dragging);
				Instance._dragging = null;
			}
			Instance.ReleaseCursor();
			HudRepositionAPI.ClearAutoDetected();
			Instance._autoConfigFiles.Clear();
		}
		IsActive = false;
		SparrohPlugin.Logger.LogInfo((object)"[HudReposition] Reposition mode OFF");
	}

	private void Update()
	{
		//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_0047: Unknown result type (might be due to invalid IL or missing references)
		if (!IsActive)
		{
			return;
		}
		FreeCursor.Apply();
		InputBlocker.SoftSuppressMouseFire();
		if (Keyboard.current != null && ((ButtonControl)Keyboard.current.escapeKey).wasPressedThisFrame)
		{
			Exit();
			return;
		}
		Mouse current = Mouse.current;
		if (current != null)
		{
			Vector2 screenPos = ((InputControl<Vector2>)(object)((Pointer)current).position).ReadValue();
			ProcessDragInput(screenPos, current.leftButton.wasPressedThisFrame, current.leftButton.isPressed, current.leftButton.wasReleasedThisFrame);
		}
	}

	private void OnGUI()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: 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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Invalid comparison between Unknown and I4
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Invalid comparison between Unknown and I4
		//IL_0046: 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_008c: Unknown result type (might be due to invalid IL or missing references)
		if (!IsActive)
		{
			return;
		}
		Event current = Event.current;
		if (current != null)
		{
			Vector2 mousePosition = current.mousePosition;
			Vector2 screenPos = default(Vector2);
			((Vector2)(ref screenPos))..ctor(mousePosition.x, (float)Screen.height - mousePosition.y);
			if ((int)current.type == 0 && current.button == 0)
			{
				ProcessDragInput(screenPos, pressed: true, held: true, released: false);
				current.Use();
			}
			else if ((int)current.type == 3 && current.button == 0)
			{
				ProcessDragInput(screenPos, pressed: false, held: true, released: false);
				current.Use();
			}
			else if ((int)current.type == 1 && current.button == 0)
			{
				ProcessDragInput(screenPos, pressed: false, held: false, released: true);
				current.Use();
			}
		}
		DrawOverlay();
	}

	private void ProcessDragInput(Vector2 screenPos, bool pressed, bool held, bool released)
	{
		//IL_0013: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		HudRepositionAPI.CleanupDestroyed();
		IReadOnlyList<HudRepositionAPI.HudElement> registered = HudRepositionAPI.GetRegistered();
		if (pressed)
		{
			_dragging = FindElementAtScreenPos(registered, screenPos);
			if (_dragging != null && (Object)(object)_dragging.Rect != (Object)null)
			{
				if (TryScreenToNormalizedParent(_dragging.Rect, screenPos, out var normalized))
				{
					_dragGrabOffset = _dragging.Rect.anchorMin - normalized;
				}
				else
				{
					_dragGrabOffset = Vector2.zero;
				}
				SparrohPlugin.Logger.LogInfo((object)("[HudReposition] Drag start: " + _dragging.DisplayName));
			}
		}
		if (_dragging != null && (Object)(object)_dragging.Rect != (Object)null && held && TryScreenToNormalizedParent(_dragging.Rect, screenPos, out var normalized2))
		{
			Vector2 val = normalized2 + _dragGrabOffset;
			val.x = Mathf.Clamp01(val.x);
			val.y = Mathf.Clamp01(val.y);
			ApplyAnchorsLive(_dragging.Rect, val);
		}
		if (released && _dragging != null)
		{
			CommitDrag(_dragging);
			_dragging = null;
		}
	}

	private void DrawOverlay()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: 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_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Expected O, but got Unknown
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Expected O, but got Unknown
		//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_027d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0289: Expected O, but got Unknown
		//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
		Rect val = new Rect(0f, 0f, (float)Screen.width, 36f);
		GUI.color = new Color(0f, 0f, 0f, 0.75f);
		GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
		GUI.color = Color.white;
		IReadOnlyList<HudRepositionAPI.HudElement> registered = HudRepositionAPI.GetRegistered();
		string text = ((registered.Count == 0) ? "HUD Reposition Mode — no HUD elements found (is the HUD visible in-mission?) · Esc/F9 to exit" : $"HUD Reposition Mode — {registered.Count} element(s) · drag boxes to move · Esc/F9 to exit");
		GUIStyle val2 = new GUIStyle(GUI.skin.label)
		{
			alignment = (TextAnchor)4,
			fontSize = 15,
			fontStyle = (FontStyle)1
		};
		val2.normal.textColor = Color.white;
		GUIStyle val3 = val2;
		GUI.Label(val, text, val3);
		Rect val7 = default(Rect);
		foreach (HudRepositionAPI.HudElement item in registered)
		{
			if ((Object)(object)item.Rect == (Object)null || !TryGetScreenRect(item.Rect, out var guiRect))
			{
				continue;
			}
			guiRect = EnsureMinHitSize(ExpandRect(guiRect, 10f, 8f));
			int num;
			Color val4;
			if (_dragging != null)
			{
				num = ((_dragging.Id == item.Id) ? 1 : 0);
				if (num != 0)
				{
					val4 = new Color(0.2f, 0.85f, 0.4f, 0.4f);
					goto IL_015f;
				}
			}
			else
			{
				num = 0;
			}
			val4 = new Color(0.2f, 0.55f, 1f, 0.35f);
			goto IL_015f;
			IL_015f:
			Color color = val4;
			Color color2 = ((num != 0) ? new Color(0.2f, 1f, 0.4f, 1f) : new Color(0.5f, 0.85f, 1f, 1f));
			GUI.color = color;
			GUI.DrawTexture(guiRect, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color2;
			DrawBorder(guiRect, 2f);
			GUI.color = Color.white;
			Vector2 anchorMin = item.Rect.anchorMin;
			string text2 = $"{item.DisplayName}  ({anchorMin.x:F3}, {anchorMin.y:F3})";
			GUIStyle val5 = new GUIStyle(GUI.skin.label)
			{
				alignment = (TextAnchor)0,
				fontSize = 13,
				fontStyle = (FontStyle)1
			};
			val5.normal.textColor = Color.white;
			GUIStyle val6 = val5;
			((Rect)(ref val7))..ctor(((Rect)(ref guiRect)).x, Mathf.Max(40f, ((Rect)(ref guiRect)).y - 18f), Mathf.Max(((Rect)(ref guiRect)).width, 240f), 18f);
			GUIStyle val8 = new GUIStyle(val6);
			val8.normal.textColor = Color.black;
			GUIStyle val9 = val8;
			GUI.Label(new Rect(((Rect)(ref val7)).x + 1f, ((Rect)(ref val7)).y + 1f, ((Rect)(ref val7)).width, ((Rect)(ref val7)).height), text2, val9);
			GUI.Label(val7, text2, val6);
		}
	}

	private void CommitDrag(HudRepositionAPI.HudElement element)
	{
		//IL_00e6: 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_0020: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)element?.Rect == (Object)null)
		{
			return;
		}
		Vector2 anchorMin = element.Rect.anchorMin;
		float num = Mathf.Clamp01(anchorMin.x);
		float num2 = Mathf.Clamp01(anchorMin.y);
		try
		{
			bool flag = false;
			if (!Mathf.Approximately(element.AnchorX.Value, num))
			{
				element.AnchorX.Value = num;
				flag = true;
			}
			if (!Mathf.Approximately(element.AnchorY.Value, num2))
			{
				element.AnchorY.Value = num2;
				flag = true;
			}
			if (flag)
			{
				((ConfigEntryBase)element.AnchorX).ConfigFile.Save();
				SparrohPlugin.Logger.LogInfo((object)$"[HudReposition] Saved '{element.DisplayName}' → ({num:F4}, {num2:F4})");
			}
		}
		catch (Exception ex)
		{
			SparrohPlugin.Logger.LogError((object)("[HudReposition] Failed to save '" + element.DisplayName + "': " + ex.Message));
		}
		ApplyAnchorsLive(element.Rect, new Vector2(num, num2));
	}

	private static void ApplyAnchorsLive(RectTransform rect, Vector2 anchors)
	{
		//IL_0001: 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_000f: Unknown result type (might be due to invalid IL or missing references)
		rect.anchorMin = anchors;
		rect.anchorMax = anchors;
		rect.anchoredPosition = Vector2.zero;
	}

	private static HudRepositionAPI.HudElement FindElementAtScreenPos(IReadOnlyList<HudRepositionAPI.HudElement> elements, Vector2 screenPos)
	{
		//IL_0035: 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_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		HudRepositionAPI.HudElement result = null;
		float num = float.MaxValue;
		foreach (HudRepositionAPI.HudElement element in elements)
		{
			if ((Object)(object)element.Rect == (Object)null || !TryGetScreenRectRaw(element.Rect, out var screenRect))
			{
				continue;
			}
			screenRect = EnsureMinHitSize(ExpandRect(screenRect, 10f, 8f));
			if (((Rect)(ref screenRect)).Contains(screenPos))
			{
				float num2 = ((Rect)(ref screenRect)).width * ((Rect)(ref screenRect)).height;
				if (num2 < num)
				{
					num = num2;
					result = element;
				}
			}
		}
		return result;
	}

	private static bool TryGetScreenRectRaw(RectTransform rect, out Rect screenRect)
	{
		//IL_0001: 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_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		screenRect = default(Rect);
		if ((Object)(object)rect == (Object)null)
		{
			return false;
		}
		Camera val = null;
		Canvas componentInParent = ((Component)rect).GetComponentInParent<Canvas>();
		if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0)
		{
			val = componentInParent.worldCamera ?? Camera.main;
		}
		Vector3[] array = (Vector3[])(object)new Vector3[4];
		rect.GetWorldCorners(array);
		float num = float.MaxValue;
		float num2 = float.MinValue;
		float num3 = float.MaxValue;
		float num4 = float.MinValue;
		Vector2 val2 = default(Vector2);
		for (int i = 0; i < 4; i++)
		{
			if ((Object)(object)val != (Object)null)
			{
				val2 = RectTransformUtility.WorldToScreenPoint(val, array[i]);
			}
			else
			{
				((Vector2)(ref val2))..ctor(array[i].x, array[i].y);
			}
			num = Mathf.Min(num, val2.x);
			num2 = Mathf.Max(num2, val2.x);
			num3 = Mathf.Min(num3, val2.y);
			num4 = Mathf.Max(num4, val2.y);
		}
		if (num2 - num < 1f || num4 - num3 < 1f)
		{
			Vector2 val3 = AnchorToScreenPoint(rect);
			screenRect = new Rect(val3.x - 90f, val3.y - 18f, 180f, 36f);
			return true;
		}
		screenRect = new Rect(num, num3, num2 - num, num4 - num3);
		return true;
	}

	private static Vector2 AnchorToScreenPoint(RectTransform rect)
	{
		//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_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: 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_002e: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		Transform parent = ((Transform)rect).parent;
		RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
		if ((Object)(object)val == (Object)null)
		{
			return new Vector2((float)Screen.width * rect.anchorMin.x, (float)Screen.height * rect.anchorMin.y);
		}
		Rect rect2 = val.rect;
		Vector2 val2 = default(Vector2);
		((Vector2)(ref val2))..ctor(((Rect)(ref rect2)).xMin + rect.anchorMin.x * ((Rect)(ref rect2)).width, ((Rect)(ref rect2)).yMin + rect.anchorMin.y * ((Rect)(ref rect2)).height);
		Vector3 val3 = ((Transform)val).TransformPoint(Vector2.op_Implicit(val2));
		Camera val4 = null;
		Canvas componentInParent = ((Component)rect).GetComponentInParent<Canvas>();
		if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0)
		{
			val4 = componentInParent.worldCamera ?? Camera.main;
		}
		if ((Object)(object)val4 != (Object)null)
		{
			return RectTransformUtility.WorldToScreenPoint(val4, val3);
		}
		return new Vector2(val3.x, val3.y);
	}

	private static bool TryGetScreenRect(RectTransform rect, out Rect guiRect)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//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)
		guiRect = default(Rect);
		if (!TryGetScreenRectRaw(rect, out var screenRect))
		{
			return false;
		}
		guiRect = new Rect(((Rect)(ref screenRect)).x, (float)Screen.height - ((Rect)(ref screenRect)).y - ((Rect)(ref screenRect)).height, ((Rect)(ref screenRect)).width, ((Rect)(ref screenRect)).height);
		return true;
	}

	private static Rect ExpandRect(Rect r, float padX, float padY)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		return new Rect(((Rect)(ref r)).x - padX, ((Rect)(ref r)).y - padY, ((Rect)(ref r)).width + padX * 2f, ((Rect)(ref r)).height + padY * 2f);
	}

	private static Rect EnsureMinHitSize(Rect r)
	{
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Max(((Rect)(ref r)).width, 180f);
		float num2 = Mathf.Max(((Rect)(ref r)).height, 36f);
		float num3 = ((Rect)(ref r)).x + ((Rect)(ref r)).width * 0.5f;
		float num4 = ((Rect)(ref r)).y + ((Rect)(ref r)).height * 0.5f;
		return new Rect(num3 - num * 0.5f, num4 - num2 * 0.5f, num, num2);
	}

	private static void DrawBorder(Rect r, float thickness)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y, ((Rect)(ref r)).width, thickness), (Texture)(object)Texture2D.whiteTexture);
		GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).yMax - thickness, ((Rect)(ref r)).width, thickness), (Texture)(object)Texture2D.whiteTexture);
		GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y, thickness, ((Rect)(ref r)).height), (Texture)(object)Texture2D.whiteTexture);
		GUI.DrawTexture(new Rect(((Rect)(ref r)).xMax - thickness, ((Rect)(ref r)).y, thickness, ((Rect)(ref r)).height), (Texture)(object)Texture2D.whiteTexture);
	}

	private static bool TryScreenToNormalizedParent(RectTransform rect, Vector2 screenPos, out Vector2 normalized)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: 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_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: 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_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		normalized = Vector2.zero;
		if ((Object)(object)rect == (Object)null)
		{
			return false;
		}
		Transform parent = ((Transform)rect).parent;
		RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
		if ((Object)(object)val == (Object)null)
		{
			normalized = new Vector2(Mathf.Clamp01(screenPos.x / Mathf.Max(1f, (float)Screen.width)), Mathf.Clamp01(screenPos.y / Mathf.Max(1f, (float)Screen.height)));
			return true;
		}
		Camera val2 = null;
		Canvas componentInParent = ((Component)rect).GetComponentInParent<Canvas>();
		if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0)
		{
			val2 = componentInParent.worldCamera ?? Camera.main;
		}
		Vector2 val3 = default(Vector2);
		if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(val, screenPos, val2, ref val3))
		{
			normalized = new Vector2(Mathf.Clamp01(screenPos.x / Mathf.Max(1f, (float)Screen.width)), Mathf.Clamp01(screenPos.y / Mathf.Max(1f, (float)Screen.height)));
			return true;
		}
		Rect rect2 = val.rect;
		if (((Rect)(ref rect2)).width <= 0f || ((Rect)(ref rect2)).height <= 0f)
		{
			return false;
		}
		normalized = new Vector2((val3.x - ((Rect)(ref rect2)).xMin) / ((Rect)(ref rect2)).width, (val3.y - ((Rect)(ref rect2)).yMin) / ((Rect)(ref rect2)).height);
		return true;
	}

	private void HoldCursor()
	{
		if (!_cursorHeld)
		{
			FreeCursor.Acquire();
			_cursorHeld = true;
		}
	}

	private void ReleaseCursor()
	{
		if (_cursorHeld)
		{
			FreeCursor.Release();
			_cursorHeld = false;
		}
	}

	private void RunAutoDetect()
	{
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Expected O, but got Unknown
		try
		{
			List<AnchorPair> list = DiscoverAnchorPairs();
			List<GameObject> list2 = FindHudRoots();
			SparrohPlugin.Logger.LogInfo((object)$"[HudReposition] Auto-detect: {list.Count} anchor pair(s), {list2.Count} HUD root(s)");
			foreach (AnchorPair pair in list)
			{
				string id = "auto::" + Path.GetFileNameWithoutExtension(pair.ConfigPath) + "::" + pair.Prefix;
				if (HudRepositionAPI.GetRegistered().Any((HudRepositionAPI.HudElement e) => e.AnchorX != null && string.Equals(((ConfigEntryBase)e.AnchorX).Definition.Key, pair.KeyX, StringComparison.OrdinalIgnoreCase) && string.Equals(((ConfigEntryBase)e.AnchorY).Definition.Key, pair.KeyY, StringComparison.OrdinalIgnoreCase)))
				{
					continue;
				}
				GameObject val = ((IEnumerable<GameObject>)list2).FirstOrDefault((Func<GameObject, bool>)((GameObject r) => NameMatchesPrefix(((Object)r).name, pair.Prefix)));
				if ((Object)(object)val == (Object)null && list2.Count > 0)
				{
					val = ((IEnumerable<GameObject>)list2).FirstOrDefault((Func<GameObject, bool>)((GameObject r) => ((Object)r).name.IndexOf(pair.Prefix.Substring(0, Math.Min(4, pair.Prefix.Length)), StringComparison.OrdinalIgnoreCase) >= 0));
				}
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				RectTransform component = val.GetComponent<RectTransform>();
				if (!((Object)(object)component == (Object)null))
				{
					if (!_autoConfigFiles.TryGetValue(pair.ConfigPath, out var value))
					{
						value = new ConfigFile(pair.ConfigPath, true);
						_autoConfigFiles[pair.ConfigPath] = value;
					}
					ConfigEntry<float> anchorX = value.Bind<float>(pair.Section, pair.KeyX, pair.DefaultX, (ConfigDescription)null);
					ConfigEntry<float> anchorY = value.Bind<float>(pair.Section, pair.KeyY, pair.DefaultY, (ConfigDescription)null);
					HudRepositionAPI.RegisterAutoDetected(id, string.IsNullOrEmpty(pair.Prefix) ? ((Object)val).name : pair.Prefix, component, anchorX, anchorY);
					SparrohPlugin.Logger.LogInfo((object)("[HudReposition] Auto-detected '" + ((Object)val).name + "' ← " + pair.KeyX + "/" + pair.KeyY));
				}
			}
		}
		catch (Exception ex)
		{
			SparrohPlugin.Logger.LogWarning((object)("[HudReposition] Auto-detect failed: " + ex.Message));
		}
	}

	private static List<AnchorPair> DiscoverAnchorPairs()
	{
		List<AnchorPair> list = new List<AnchorPair>();
		if (!Directory.Exists(Paths.ConfigPath))
		{
			return list;
		}
		string[] files = Directory.GetFiles(Paths.ConfigPath, "*.cfg");
		foreach (string text in files)
		{
			try
			{
				string item = "";
				Dictionary<string, (string, float)> dictionary = new Dictionary<string, (string, float)>(StringComparer.OrdinalIgnoreCase);
				foreach (string item2 in File.ReadLines(text))
				{
					string text2 = item2.Trim();
					if (text2.Length == 0 || text2.StartsWith("#"))
					{
						continue;
					}
					if (text2.StartsWith("[") && text2.EndsWith("]"))
					{
						item = text2.Substring(1, text2.Length - 2);
						continue;
					}
					int num = text2.IndexOf('=');
					if (num > 0)
					{
						string key = text2.Substring(0, num).Trim();
						string s = text2.Substring(num + 1).Trim();
						if (float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || float.TryParse(s, NumberStyles.Float, CultureInfo.CurrentCulture, out result))
						{
							dictionary[key] = (item, result);
						}
					}
				}
				foreach (KeyValuePair<string, (string, float)> item3 in dictionary)
				{
					Match match = AnchorPairRegex.Match(item3.Key);
					if (match.Success)
					{
						string value = match.Groups["prefix"].Value;
						string text3 = value + "AnchorY";
						if (dictionary.TryGetValue(text3, out var value2))
						{
							list.Add(new AnchorPair
							{
								ConfigPath = text,
								Section = (string.IsNullOrEmpty(item3.Value.Item1) ? "HUD Positioning" : item3.Value.Item1),
								Prefix = value,
								KeyX = item3.Key,
								KeyY = text3,
								DefaultX = item3.Value.Item2,
								DefaultY = value2.Item2
							});
						}
					}
				}
			}
			catch (Exception ex)
			{
				SparrohPlugin.Logger.LogDebug((object)("[HudReposition] Could not parse " + text + ": " + ex.Message));
			}
		}
		return list;
	}

	private static List<GameObject> FindHudRoots()
	{
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Expected O, but got Unknown
		List<GameObject> roots = new List<GameObject>();
		HashSet<int> seen = new HashSet<int>();
		try
		{
			Type type = Type.GetType("Pigeon.Movement.Player, Assembly-CSharp") ?? AppDomain.CurrentDomain.GetAssemblies().SelectMany(delegate(Assembly a)
			{
				try
				{
					return a.GetTypes();
				}
				catch
				{
					return Type.EmptyTypes;
				}
			}).FirstOrDefault((Type t) => t.Name == "Player" && t.Namespace != null && t.Namespace.Contains("Pigeon"));
			if (type != null)
			{
				object obj = type.GetProperty("LocalPlayer", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
				if (obj != null)
				{
					object obj2 = (obj.GetType().GetProperty("PlayerLook") ?? obj.GetType().GetProperty("playerLook"))?.GetValue(obj);
					if (obj2 != null)
					{
						object? obj3 = (obj2.GetType().GetProperty("Reticle") ?? obj2.GetType().GetProperty("reticle"))?.GetValue(obj2);
						Transform val = (Transform)((obj3 is Transform) ? obj3 : null);
						if ((Object)(object)val != (Object)null)
						{
							foreach (Transform item in val)
							{
								Transform val2 = item;
								if ((Object)(object)((Component)val2).GetComponent<RectTransform>() != (Object)null)
								{
									Add(((Component)val2).gameObject);
								}
							}
							SparrohPlugin.Logger.LogInfo((object)$"[HudReposition] Found reticle with {val.childCount} child(ren)");
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			SparrohPlugin.Logger.LogDebug((object)("[HudReposition] Reticle scan failed: " + ex.Message));
		}
		try
		{
			RectTransform[] array = Object.FindObjectsOfType<RectTransform>();
			foreach (RectTransform val3 in array)
			{
				string name = ((Object)((Component)val3).gameObject).name;
				if (name.IndexOf("HUD", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Meter", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Speedometer", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Altimeter", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Carnometer", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Tracker", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("GunStats", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("BossTimer", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					Add(((Component)val3).gameObject);
				}
			}
		}
		catch (Exception ex2)
		{
			SparrohPlugin.Logger.LogDebug((object)("[HudReposition] Global HUD scan failed: " + ex2.Message));
		}
		return roots;
		void Add(GameObject go)
		{
			if (!((Object)(object)go == (Object)null))
			{
				int instanceID = ((Object)go).GetInstanceID();
				if (seen.Add(instanceID))
				{
					roots.Add(go);
				}
			}
		}
	}

	private static bool NameMatchesPrefix(string goName, string prefix)
	{
		if (string.IsNullOrEmpty(goName) || string.IsNullOrEmpty(prefix))
		{
			return false;
		}
		string text = goName.Replace(" ", "").Replace("_", "");
		string text2 = prefix.Replace(" ", "").Replace("_", "");
		if (text.IndexOf(text2, StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		if (text2.StartsWith("Gun", StringComparison.OrdinalIgnoreCase) && text.IndexOf("Gun", StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		if (text2.Length >= 4)
		{
			string value = text2.Substring(0, Math.Min(8, text2.Length));
			if (text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
		}
		return false;
	}
}
public static class InputBlocker
{
	private static bool _patched;

	private static Harmony _harmony;

	public static bool ShouldBlockGameplayInput
	{
		get
		{
			if (!FreeCursor.IsHeld && !HudRepositionMode.IsActive)
			{
				return ModConfigGUI.IsVisible;
			}
			return true;
		}
	}

	public static void EnsurePatched(Harmony harmony)
	{
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: Expected O, but got Unknown
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Expected O, but got Unknown
		if (_patched)
		{
			return;
		}
		_harmony = harmony;
		try
		{
			Type type = AccessTools.TypeByName("Gun") ?? AccessTools.TypeByName("Pigeon.Gun") ?? FindTypeBySimpleName("Gun");
			if (type != null)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.IsSpecialName || methodInfo.IsGenericMethod)
					{
						continue;
					}
					string name = methodInfo.Name;
					if ((name.IndexOf("Fire", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Shoot", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Attack", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("Primary", StringComparison.OrdinalIgnoreCase) >= 0) && name.IndexOf("OnFired", StringComparison.OrdinalIgnoreCase) < 0)
					{
						try
						{
							HarmonyMethod val = new HarmonyMethod(typeof(InputBlocker), "BlockIfUiOpen", (Type[])null);
							harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
							SparrohPlugin.Logger.LogInfo((object)("[InputBlocker] Patched " + type.Name + "." + methodInfo.Name));
						}
						catch (Exception ex)
						{
							SparrohPlugin.Logger.LogDebug((object)("[InputBlocker] Skip " + methodInfo.Name + ": " + ex.Message));
						}
					}
				}
			}
			Type type2 = AccessTools.TypeByName("Pigeon.Movement.Player") ?? AccessTools.TypeByName("Player");
			if (type2 != null)
			{
				MethodInfo[] methods = type2.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo2 in methods)
				{
					string name2 = methodInfo2.Name;
					if (name2.IndexOf("Fire", StringComparison.OrdinalIgnoreCase) >= 0 || name2.IndexOf("Shoot", StringComparison.OrdinalIgnoreCase) >= 0 || name2.IndexOf("Attack", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						try
						{
							HarmonyMethod val2 = new HarmonyMethod(typeof(InputBlocker), "BlockIfUiOpen", (Type[])null);
							harmony.Patch((MethodBase)methodInfo2, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
							SparrohPlugin.Logger.LogInfo((object)("[InputBlocker] Patched " + type2.Name + "." + methodInfo2.Name));
						}
						catch
						{
						}
					}
				}
			}
			_patched = true;
		}
		catch (Exception ex2)
		{
			SparrohPlugin.Logger.LogWarning((object)("[InputBlocker] Patch setup failed: " + ex2.Message));
		}
	}

	public static bool BlockIfUiOpen()
	{
		return !ShouldBlockGameplayInput;
	}

	public static void SoftSuppressMouseFire()
	{
		_ = ShouldBlockGameplayInput;
	}

	private static Type FindTypeBySimpleName(string simpleName)
	{
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		foreach (Assembly assembly in assemblies)
		{
			try
			{
				Type type = assembly.GetTypes().FirstOrDefault((Type x) => x.Name == simpleName);
				if (type != null)
				{
					return type;
				}
			}
			catch
			{
			}
		}
		return null;
	}
}
public class ModConfigGUI : MonoBehaviour
{
	private sealed class ModBlockState
	{
		public string Key;

		public GameObject Body;

		public TextMeshProUGUI Chevron;

		public RectTransform TitleRect;

		public string TitleRichText;

		public bool IsExpanded;
	}

	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static Action <>9__50_0;

		public static Action <>9__50_1;

		public static Action<string> <>9__51_0;

		public static Action <>9__51_1;

		public static UnityAction <>9__51_2;

		public static Action<int, string> <>9__51_3;

		public static Action<bool> <>9__51_4;

		public static Action<bool> <>9__51_5;

		public static Action <>9__51_6;

		public static Comparison<ModInfo> <>9__82_0;

		public static Comparison<ModInfo> <>9__82_1;

		public static Comparison<ModInfo> <>9__82_2;

		public static Comparison<ModInfo> <>9__82_3;

		public static Func<string, string> <>9__91_0;

		internal void <CreateGUI>b__50_0()
		{
			if (_visible)
			{
				_visible = false;
				ClearActiveEditing();
				ReleaseCursor();
				if ((Object)(object)EventSystem.current != (Object)null)
				{
					EventSystem.current.SetSelectedGameObject((GameObject)null);
				}
			}
		}

		internal void <CreateGUI>b__50_1()
		{
			Hide();
			HudRepositionMode.Enter();
		}

		internal void <CreateToolbar>b__51_0(string query)
		{
			if (!_suppressToolbarCallbacks)
			{
				_searchQuery = query ?? "";
				RefreshMods(resetScroll: true, preserveSearchFocus: true);
			}
		}

		internal void <CreateToolbar>b__51_1()
		{
			if (!_suppressToolbarCallbacks)
			{
				SetToolbarFiltersCollapsed(!_toolbarFiltersCollapsed, persist: true);
			}
		}

		internal void <CreateToolbar>b__51_2()
		{
			bool isOpen = _sortDropdown.IsOpen;
			ClearActiveEditing();
			if (!isOpen)
			{
				_sortDropdown.OpenList();
				RegisterOpenDropdown(_sortDropdown);
			}
		}

		internal void <CreateToolbar>b__51_3(int idx, string _)
		{
			if (!_suppressToolbarCallbacks)
			{
				string text = SortModeIds[Mathf.Clamp(idx, 0, SortModeIds.Length - 1)];
				if (SparrohPlugin.ModSortMode != null && SparrohPlugin.ModSortMode.Value != text)
				{
					SparrohPlugin.ModSortMode.Value = text;
					((ConfigEntryBase)SparrohPlugin.ModSortMode).ConfigFile.Save();
				}
				UnregisterDropdown(_sortDropdown);
				RefreshMods(resetScroll: true);
			}
		}

		internal void <CreateToolbar>b__51_4(bool val)
		{
			if (!_suppressToolbarCallbacks)
			{
				if (SparrohPlugin.HideModsWithoutConfig != null && SparrohPlugin.HideModsWithoutConfig.Value != val)
				{
					SparrohPlugin.HideModsWithoutConfig.Value = val;
					((ConfigEntryBase)SparrohPlugin.HideModsWithoutConfig).ConfigFile.Save();
				}
				RefreshMods(resetScroll: true);
			}
		}

		internal void <CreateToolbar>b__51_5(bool val)
		{
			if (!_suppressToolbarCallbacks)
			{
				if (SparrohPlugin.GroupModsByAuthor != null && SparrohPlugin.GroupModsByAuthor.Value != val)
				{
					SparrohPlugin.GroupModsByAuthor.Value = val;
					((ConfigEntryBase)SparrohPlugin.GroupModsByAuthor).ConfigFile.Save();
				}
				RefreshMods(resetScroll: true);
			}
		}

		internal void <CreateToolbar>b__51_6()
		{
			if (!_suppressToolbarCallbacks)
			{
				ToggleExpandCollapseAll();
			}
		}

		internal int <SortMods>b__82_0(ModInfo a, ModInfo b)
		{
			return string.Compare(((ModInfo)(ref b)).Name, ((ModInfo)(ref a)).Name, StringComparison.OrdinalIgnoreCase);
		}

		internal int <SortMods>b__82_1(ModInfo a, ModInfo b)
		{
			int num = ((ModInfo)(ref b)).IsSandbox.CompareTo(((ModInfo)(ref a)).IsSandbox);
			if (num != 0)
			{
				return num;
			}
			return string.Compare(((ModInfo)(ref a)).Name, ((ModInfo)(ref b)).Name, StringComparison.OrdinalIgnoreCase);
		}

		internal int <SortMods>b__82_2(ModInfo a, ModInfo b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			bool value = ModHasConfig(a);
			int num = ModHasConfig(b).CompareTo(value);
			if (num != 0)
			{
				return num;
			}
			return string.Compare(((ModInfo)(ref a)).Name, ((ModInfo)(ref b)).Name, StringComparison.OrdinalIgnoreCase);
		}

		internal int <SortMods>b__82_3(ModInfo a, ModInfo b)
		{
			return string.Compare(((ModInfo)(ref a)).Name, ((ModInfo)(ref b)).Name, StringComparison.OrdinalIgnoreCase);
		}

		internal string <ParseModConfig>b__91_0(string s)
		{
			return s.Trim();
		}
	}

	private const float ClickDragThresholdPx = 8f;

	private const float FontTitleRef = 26f;

	private const float FontModTitleRef = 22f;

	private const float FontSectionRef = 18f;

	private const float FontLabelRef = 17f;

	private const float FontBodyRef = 16f;

	private const float FontSmallRef = 14f;

	private static UIWindow _window;

	private static bool _visible;

	private static bool _cursorHeld;

	private static TMP_InputField _activeInput;

	private static readonly List<UIDropdown> _openDropdowns = new List<UIDropdown>();

	private static StickyModTitleController _stickyTitles;

	private static RectTransform _toolbarRoot;

	private static RectTransform _toolbarFiltersBody;

	private static RectTransform _toolbarScrollRt;

	private static UIInputField _searchField;

	private static UIDropdown _sortDropdown;

	private static UIToggle _hideEmptyToggle;

	private static UIToggle _groupByAuthorToggle;

	private static UIButton _expandCollapseAllBtn;

	private static UIButton _toolbarFiltersToggleBtn;

	private static readonly List<UIButton> _filterChipButtons = new List<UIButton>();

	private static string _searchQuery = "";

	private static bool _suppressToolbarCallbacks;

	private static bool _toolbarFiltersCollapsed;

	private static float _toolbarHExpanded;

	private static float _toolbarHCollapsed;

	private static string[] _cfgFilesCache;

	private static readonly HashSet<string> _collapsedMods = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	private static readonly List<ModBlockState> _modBlocks = new List<ModBlockState>();

	private static readonly string[] SortModeIds = new string[5] { "Alphabetical", "AlphabeticalDesc", "LoadOrder", "SandboxFirst", "HasConfigFirst" };

	private static readonly string[] SortModeLabels = new string[5] { "A–Z", "Z–A", "Load order", "Sandbox first", "Has config first" };

	private static readonly string[] FilterChipIds = new string[3] { "All", "Sandbox", "ClientSide" };

	private static readonly string[] FilterChipLabels = new string[3] { "All", "Sandbox", "Client-side" };

	public static TMP_InputField KeyBindInput;

	public static TMP_InputField RepositionKeyBindInput;

	private static Dictionary<string, Dictionary<string, string[]>> _cachedOptions = new Dictionary<string, Dictionary<string, string[]>>();

	public static bool IsVisible => _visible;

	internal static void ClearActiveEditing()
	{
		if ((Object)(object)_activeInput != (Object)null)
		{
			_activeInput.DeactivateInputField(false);
			_activeInput = null;
		}
		for (int num = _openDropdowns.Count - 1; num >= 0; num--)
		{
			UIDropdown val = _openDropdowns[num];
			if (val != null)
			{
				val.CloseList();
			}
		}
		_openDropdowns.Clear();
		if ((Object)(object)EventSystem.current != (Object)null)
		{
			EventSystem.current.SetSelectedGameObject((GameObject)null);
		}
	}

	private static void RegisterOpenDropdown(UIDropdown dropdown)
	{
		if (dropdown != null && !_openDropdowns.Contains(dropdown))
		{
			_openDropdowns.Add(dropdown);
		}
	}

	private static void UnregisterDropdown(UIDropdown dropdown)
	{
		_openDropdowns.Remove(dropdown);
	}

	private static void ActivateInput(TMP_InputField input)
	{
		if (!((Object)(object)input == (Object)null))
		{
			if ((Object)(object)_activeInput != (Object)null && (Object)(object)_activeInput != (Object)(object)input)
			{
				_activeInput.DeactivateInputField(false);
			}
			_activeInput = input;
			((Selectable)input).interactable = true;
			input.ActivateInputField();
			if ((Object)(object)EventSystem.current != (Object)null)
			{
				EventSystem.current.SetSelectedGameObject(((Component)input).gameObject);
			}
		}
	}

	public static void Toggle()
	{
		if (_window == null || (Object)(object)_window.GameObject == (Object)null)
		{
			try
			{
				CreateGUI();
			}
			catch (Exception arg)
			{
				SparrohPlugin.Logger.LogError((object)$"Error creating GUI: {arg}");
				return;
			}
		}
		if (_visible)
		{
			Hide();
		}
		else
		{
			Show();
		}
	}

	public static void Show()
	{
		if (_window == null || (Object)(object)_window.GameObject == (Object)null)
		{
			try
			{
				CreateGUI();
			}
			catch (Exception arg)
			{
				SparrohPlugin.Logger.LogError((object)$"Error creating GUI: {arg}");
				return;
			}
		}
		if (!_visible)
		{
			if (HudRepositionMode.IsActive)
			{
				HudRepositionMode.Exit();
			}
			_visible = true;
			_window.Show();
			HoldCursor();
			_searchQuery = "";
			if (_searchField != null)
			{
				_suppressToolbarCallbacks = true;
				_searchField.Text = "";
				_suppressToolbarCallbacks = false;
			}
			SyncToolbarFromConfig();
			RefreshMods(resetScroll: true);
			if ((Object)(object)EventSystem.current != (Object)null)
			{
				EventSystem.current.SetSelectedGameObject((GameObject)null);
			}
		}
	}

	public static void Hide()
	{
		if (_visible)
		{
			_visible = false;
			ClearActiveEditing();
			if (_window != null)
			{
				_window.Hide(false);
			}
			ReleaseCursor();
			if ((Object)(object)EventSystem.current != (Object)null)
			{
				EventSystem.current.SetSelectedGameObject((GameObject)null);
			}
		}
	}

	private static void HoldCursor()
	{
		if (!_cursorHeld)
		{
			FreeCursor.Acquire();
			_cursorHeld = true;
		}
	}

	private static void ReleaseCursor()
	{
		if (_cursorHeld)
		{
			FreeCursor.Release();
			_cursorHeld = false;
		}
	}

	private static void CreateGUI()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		UITheme.Initialize();
		_window = UIWindow.Create("ModConfig", (Vector2?)new Vector2(520f, 640f), "Mod Configs", true, true, (int?)(UITheme.WindowSortingOrder + 10));
		_window.OnClose((Action)delegate
		{
			if (_visible)
			{
				_visible = false;
				ClearActiveEditing();
				ReleaseCursor();
				if ((Object)(object)EventSystem.current != (Object)null)
				{
					EventSystem.current.SetSelectedGameObject((GameObject)null);
				}
			}
		});
		if ((Object)(object)_window.TitleText != (Object)null)
		{
			((TMP_Text)_window.TitleText).fontSize = UITheme.S(26f);
			((TMP_Text)_window.TitleText).fontStyle = (FontStyles)1;
			((Graphic)_window.TitleText).color = UIColors.TextPrimary;
			((TMP_Text)_window.TitleText).alignment = (TextAlignmentOptions)513;
			UIHelpers.SetFillParent(((TMP_Text)_window.TitleText).rectTransform, UITheme.S(8f));
			((TMP_Text)_window.TitleText).rectTransform.offsetMax = new Vector2(0f - UITheme.S(200f), 0f - UITheme.S(4f));
			((TMP_Text)_window.TitleText).rectTransform.offsetMin = new Vector2(UITheme.S(10f), UITheme.S(4f));
		}
		try
		{
			RectTransform val = (RectTransform)(((Object)(object)_window.TitleText != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val != (Object)null)
			{
				UIButton val2 = UIButton.Create((Transform)(object)val, "Reposition HUDs", (Action)delegate
				{
					Hide();
					HudRepositionMode.Enter();
				}, (UIButtonStyle)1, "RepositionButton", (float?)UITheme.S(28f));
				RectTransform rect = val2.Rect;
				Vector2 anchorMin = (rect.anchorMax = new Vector2(1f, 0.5f));
				rect.anchorMin = anchorMin;
				rect.pivot = new Vector2(1f, 0.5f);
				rect.sizeDelta = new Vector2(UITheme.S(150f), UITheme.S(28f));
				rect.anchoredPosition = new Vector2(0f - UITheme.S(48f), 0f);
				LayoutElement component = val2.GameObject.GetComponent<LayoutElement>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				if ((Object)(object)val2.Label != (Object)null)
				{
					((TMP_Text)val2.Label).fontSize = UITheme.S(14f);
					((TMP_Text)val2.Label).fontStyle = (FontStyles)1;
				}
			}
		}
		catch (Exception ex)
		{
			SparrohPlugin.Logger.LogWarning((object)("Could not add Reposition button to title bar: " + ex.Message));
		}
		if (_window.ScrollView != null)
		{
			ScrollRect scrollRect = _window.ScrollView.ScrollRect;
			scrollRect.scrollSensitivity = 0f;
			_stickyTitles = CreateStickyModTitleOverlay(_window.ScrollView);
			_window.ScrollView.GameObject.AddComponent<ItemStepScrollHandler>().Initialize(scrollRect, _stickyTitles);
			CreateToolbar(_window.ScrollView);
		}
		_window.Hide(false);
		_visible = false;
	}

	private static void CreateToolbar(UIScrollView scrollView)
	{
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Expected O, but got Unknown
		//IL_0412: Unknown result type (might be due to invalid IL or missing references)
		//IL_0421: Expected O, but got Unknown
		//IL_046f: Unknown result type (might be due to invalid IL or missing references)
		//IL_047e: Expected O, but got Unknown
		//IL_0560: Unknown result type (might be due to invalid IL or missing references)
		//IL_0565: Unknown result type (might be due to invalid IL or missing references)
		//IL_056b: Expected O, but got Unknown
		//IL_0692: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a1: Expected O, but got Unknown
		//IL_0815: Unknown result type (might be due to invalid IL or missing references)
		//IL_0824: Expected O, but got Unknown
		Transform parent = ((Transform)scrollView.Rect).parent;
		RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		float num = UITheme.S(4f);
		float num2 = UITheme.S(34f);
		float num3 = UITheme.S(30f);
		float num4 = UITheme.S(5f);
		_toolbarHExpanded = num + num2 + num4 + num3 + num4 + num3 + num4 + num3 + num;
		_toolbarHCollapsed = num + num2 + num;
		_toolbarScrollRt = scrollView.Rect;
		_toolbarFiltersCollapsed = SparrohPlugin.ToolbarFiltersCollapsed?.Value ?? false;
		float num5 = (_toolbarFiltersCollapsed ? _toolbarHCollapsed : _toolbarHExpanded);
		_toolbarScrollRt.offsetMax = new Vector2(_toolbarScrollRt.offsetMax.x, 0f - num5);
		Image obj = UIFactory.CreateImage("Toolbar", (Transform)(object)val, UIColors.Surface, true);
		UIFactory.ApplyWhiteSprite(obj);
		_toolbarRoot = ((Graphic)obj).rectTransform;
		UIHelpers.SetTopStretch(_toolbarRoot, num5, 0f, 0f, 0f);
		((Transform)_toolbarRoot).SetAsLastSibling();
		Image obj2 = UIFactory.CreateImage("ToolbarAccent", (Transform)(object)_toolbarRoot, UIColors.BorderAccent, false);
		UIFactory.ApplyWhiteSprite(obj2);
		RectTransform rectTransform = ((Graphic)obj2).rectTransform;
		rectTransform.anchorMin = new Vector2(0f, 0f);
		rectTransform.anchorMax = new Vector2(1f, 0f);
		rectTransform.pivot = new Vector2(0.5f, 0f);
		rectTransform.sizeDelta = new Vector2(0f, UITheme.S(2f));
		rectTransform.anchoredPosition = Vector2.zero;
		((Component)obj2).gameObject.AddComponent<LayoutElement>().ignoreLayout = true;
		UIFactory.AddVerticalLayout(((Component)obj).gameObject, num4, UITheme.ScaledPadding(8, 8, 6, 8), (TextAnchor)0, true, false, true, true);
		RectTransform obj3 = UIFactory.CreateRect("SearchRow", (Transform)(object)_toolbarRoot);
		GameObject gameObject = ((Component)obj3).gameObject;
		float? num6 = num2;
		float? num7 = num2;
		UIHelpers.EnsureLayoutElement(gameObject, (float?)null, num6, num7);
		UIFactory.AddHorizontalLayout(((Component)obj3).gameObject, UITheme.S(6f), new RectOffset(0, 0, 0, 0), (TextAnchor)3, true, false, true, true);
		_searchField = UIInputField.Create((Transform)(object)obj3, "", "Search mods…", (Action<string>)delegate(string query)
		{
			if (!_suppressToolbarCallbacks)
			{
				_searchQuery = query ?? "";
				RefreshMods(resetScroll: true, preserveSearchFocus: true);
			}
		}, "SearchField");
		GameObject gameObject2 = _searchField.GameObject;
		num7 = num2;
		num6 = num2;
		UIHelpers.EnsureLayoutElement(gameObject2, (float?)null, num7, num6).flexibleWidth = 1f;
		if ((Object)(object)_searchField.TextComponent != (Object)null)
		{
			((TMP_Text)_searchField.TextComponent).fontSize = UITheme.S(16f);
			((TMP_Text)_searchField.TextComponent).alignment = (TextAlignmentOptions)513;
		}
		if ((Object)(object)_searchField.Placeholder != (Object)null)
		{
			((TMP_Text)_searchField.Placeholder).fontSize = UITheme.S(16f);
			((TMP_Text)_searchField.Placeholder).alignment = (TextAlignmentOptions)513;
		}
		_toolbarFiltersToggleBtn = UIButton.Create((Transform)(object)obj3, _toolbarFiltersCollapsed ? "+" : "-", (Action)delegate
		{
			if (!_suppressToolbarCallbacks)
			{
				SetToolbarFiltersCollapsed(!_toolbarFiltersCollapsed, persist: true);
			}
		}, (UIButtonStyle)0, "ToolbarFiltersToggle", (float?)num2);
		UIHelpers.EnsureLayoutElement(_toolbarFiltersToggleBtn.GameObject, (float?)num2, (float?)num2, (float?)num2).flexibleWidth = 0f;
		if ((Object)(object)_toolbarFiltersToggleBtn.Label != (Object)null)
		{
			((TMP_Text)_toolbarFiltersToggleBtn.Label).fontSize = UITheme.S(22f);
			((TMP_Text)_toolbarFiltersToggleBtn.Label).fontStyle = (FontStyles)1;
		}
		_toolbarFiltersBody = UIFactory.CreateRect("FiltersBody", (Transform)(object)_toolbarRoot);
		float value = num3 + num4 + num3 + num4 + num3;
		GameObject gameObject3 = ((Component)_toolbarFiltersBody).gameObject;
		num6 = value;
		num7 = value;
		UIHelpers.EnsureLayoutElement(gameObject3, (float?)null, num6, num7);
		UIFactory.AddVerticalLayout(((Component)_toolbarFiltersBody).gameObject, num4, new RectOffset(0, 0, 0, 0), (TextAnchor)0, true, false, true, true);
		RectTransform obj4 = UIFactory.CreateRect("SortRow", (Transform)(object)_toolbarFiltersBody);
		GameObject gameObject4 = ((Component)obj4).gameObject;
		num7 = num3;
		num6 = num3;
		UIHelpers.EnsureLayoutElement(gameObject4, (float?)null, num7, num6);
		UIFactory.AddHorizontalLayout(((Component)obj4).gameObject, UITheme.S(8f), new RectOffset(0, 0, 0, 0), (TextAnchor)3, true, false, true, true);
		int num8 = IndexOfSortMode(SparrohPlugin.ModSortMode?.Value);
		_sortDropdown = UIDropdown.Create((Transform)(object)obj4, (IList<string>)SortModeLabels, num8, (Action<int, string>)null, "SortDropdown");
		UIHelpers.EnsureLayoutElement(_sortDropdown.GameObject, (float?)UITheme.S(160f), (float?)num3, (float?)num3).flexibleWidth = 1f;
		if ((Object)(object)_sortDropdown.Label != (Object)null)
		{
			((TMP_Text)_sortDropdown.Label).fontSize = UITheme.S(14f);
			((TMP_Text)_sortDropdown.Label).fontStyle = (FontStyles)1;
		}
		Button componentInChildren = _sortDropdown.GameObject.GetComponentInChildren<Button>();
		if ((Object)(object)componentInChildren != (Object)null)
		{
			((UnityEventBase)componentInChildren.onClick).RemoveAllListeners();
			ButtonClickedEvent onClick = componentInChildren.onClick;
			object obj5 = <>c.<>9__51_2;
			if (obj5 == null)
			{
				UnityAction val2 = delegate
				{
					bool isOpen = _sortDropdown.IsOpen;
					ClearActiveEditing();
					if (!isOpen)
					{
						_sortDropdown.OpenList();
						RegisterOpenDropdown(_sortDropdown);
					}
				};
				<>c.<>9__51_2 = val2;
				obj5 = (object)val2;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj5);
		}
		_sortDropdown.OnChanged((Action<int, string>)delegate(int idx, string _)
		{
			if (!_suppressToolbarCallbacks)
			{
				string text3 = SortModeIds[Mathf.Clamp(idx, 0, SortModeIds.Length - 1)];
				if (SparrohPlugin.ModSortMode != null && SparrohPlugin.ModSortMode.Value != text3)
				{
					SparrohPlugin.ModSortMode.Value = text3;
					((ConfigEntryBase)SparrohPlugin.ModSortMode).ConfigFile.Save();
				}
				UnregisterDropdown(_sortDropdown);
				RefreshMods(resetScroll: true);
			}
		});
		_hideEmptyToggle = UIToggle.Create((Transform)(object)obj4, "Hide empty", SparrohPlugin.HideModsWithoutConfig?.Value ?? true, (Action<bool>)delegate(bool flag2)
		{
			if (!_suppressToolbarCallbacks)
			{
				if (SparrohPlugin.HideModsWithoutConfig != null && SparrohPlugin.HideModsWithoutConfig.Value != flag2)
				{
					SparrohPlugin.HideModsWithoutConfig.Value = flag2;
					((ConfigEntryBase)SparrohPlugin.HideModsWithoutConfig).ConfigFile.Save();
				}
				RefreshMods(resetScroll: true);
			}
		}, "HideEmptyToggle");
		UIHelpers.EnsureLayoutElement(_hideEmptyToggle.GameObject, (float?)UITheme.S(120f), (float?)num3, (float?)null).flexibleWidth = 0f;
		if ((Object)(object)_hideEmptyToggle.Label != (Object)null)
		{
			((TMP_Text)_hideEmptyToggle.Label).fontSize = UITheme.S(14f);
		}
		RectTransform val3 = UIFactory.CreateRect("ChipRow", (Transform)(object)_toolbarFiltersBody);
		GameObject gameObject5 = ((Component)val3).gameObject;
		num6 = num3;
		num7 = num3;
		UIHelpers.EnsureLayoutElement(gameObject5, (float?)null, num6, num7);
		UIFactory.AddHorizontalLayout(((Component)val3).gameObject, UITheme.S(6f), new RectOffset(0, 0, 0, 0), (TextAnchor)3, true, true, true, true);
		_filterChipButtons.Clear();
		string b = NormalizeFilter(SparrohPlugin.ModListFilter?.Value);
		for (int num9 = 0; num9 < FilterChipIds.Length; num9++)
		{
			string text = FilterChipIds[num9];
			string text2 = FilterChipLabels[num9];
			bool flag = string.Equals(text, b, StringComparison.OrdinalIgnoreCase);
			UIButton val4 = UIButton.Create((Transform)(object)val3, text2, (Action)null, (UIButtonStyle)(flag ? 3 : 0), "Filter_" + text, (float?)num3);
			GameObject gameObject6 = val4.GameObject;
			num7 = num3;
			num6 = num3;
			LayoutElement obj6 = UIHelpers.EnsureLayoutElement(gameObject6, (float?)null, num7, num6);
			obj6.flexibleWidth = 1f;
			obj6.preferredWidth = -1f;
			if ((Object)(object)val4.Label != (Object)null)
			{
				((TMP_Text)val4.Label).fontSize = UITheme.S(14f);
				((TMP_Text)val4.Label).fontStyle = (FontStyles)1;
			}
			string capturedId = text;
			val4.OnClick((Action)delegate
			{
				if (!_suppressToolbarCallbacks)
				{
					ApplyFilterChip(capturedId);
				}
			});
			_filterChipButtons.Add(val4);
		}
		RectTransform obj7 = UIFactory.CreateRect("DensityRow", (Transform)(object)_toolbarFiltersBody);
		GameObject gameObject7 = ((Component)obj7).gameObject;
		num6 = num3;
		num7 = num3;
		UIHelpers.EnsureLayoutElement(gameObject7, (float?)null, num6, num7);
		UIFactory.AddHorizontalLayout(((Component)obj7).gameObject, UITheme.S(8f), new RectOffset(0, 0, 0, 0), (TextAnchor)3, true, false, true, true);
		_groupByAuthorToggle = UIToggle.Create((Transform)(object)obj7, "Group by author", SparrohPlugin.GroupModsByAuthor?.Value ?? false, (Action<bool>)delegate(bool flag2)
		{
			if (!_suppressToolbarCallbacks)
			{
				if (SparrohPlugin.GroupModsByAuthor != null && SparrohPlugin.GroupModsByAuthor.Value != flag2)
				{
					SparrohPlugin.GroupModsByAuthor.Value = flag2;
					((ConfigEntryBase)SparrohPlugin.GroupModsByAuthor).ConfigFile.Save();
				}
				RefreshMods(resetScroll: true);
			}
		}, "GroupByAuthorToggle");
		UIHelpers.EnsureLayoutElement(_groupByAuthorToggle.GameObject, (float?)UITheme.S(150f), (float?)num3, (float?)null).flexibleWidth = 1f;
		if ((Object)(object)_groupByAuthorToggle.Label != (Object)null)
		{
			((TMP_Text)_groupByAuthorToggle.Label).fontSize = UITheme.S(14f);
		}
		_expandCollapseAllBtn = UIButton.Create((Transform)(object)obj7, "Collapse all", (Action)delegate
		{
			if (!_suppressToolbarCallbacks)
			{
				ToggleExpandCollapseAll();
			}
		}, (UIButtonStyle)0, "ExpandCollapseAll", (float?)num3);
		UIHelpers.EnsureLayoutElement(_expandCollapseAllBtn.GameObject, (float?)UITheme.S(120f), (float?)num3, (float?)null).flexibleWidth = 0f;
		if ((Object)(object)_expandCollapseAllBtn.Label != (Object)null)
		{
			((TMP_Text)_expandCollapseAllBtn.Label).fontSize = UITheme.S(14f);
			((TMP_Text)_expandCollapseAllBtn.Label).fontStyle = (FontStyles)1;
		}
		ApplyToolbarFiltersCollapsed(persist: false);
	}

	private static void SetToolbarFiltersCollapsed(bool collapsed, bool persist)
	{
		_toolbarFiltersCollapsed = collapsed;
		ApplyToolbarFiltersCollapsed(persist);
	}

	private static void ApplyToolbarFiltersCollapsed(bool persist)
	{
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_toolbarFiltersBody != (Object)null)
		{
			((Component)_toolbarFiltersBody).gameObject.SetActive(!_toolbarFiltersCollapsed);
		}
		float num = (_toolbarFiltersCollapsed ? _toolbarHCollapsed : _toolbarHExpanded);
		if ((Object)(object)_toolbarRoot != (Object)null)
		{
			UIHelpers.SetTopStretch(_toolbarRoot, num, 0f, 0f, 0f);
		}
		if ((Object)(object)_toolbarScrollRt != (Object)null)
		{
			_toolbarScrollRt.offsetMax = new Vector2(_toolbarScrollRt.offsetMax.x, 0f - num);
		}
		if (_toolbarFiltersToggleBtn != null)
		{
			_toolbarFiltersToggleBtn.SetText(_toolbarFiltersCollapsed ? "+" : "-");
		}
		if (_toolbarFiltersCollapsed && _sortDropdown != null)
		{
			_sortDropdown.CloseList();
			UnregisterDropdown(_sortDropdown);
		}
		if (persist && SparrohPlugin.ToolbarFiltersCollapsed != null && SparrohPlugin.ToolbarFiltersCollapsed.Value != _toolbarFiltersCollapsed)
		{
			SparrohPlugin.ToolbarFiltersCollapsed.Value = _toolbarFiltersCollapsed;
			((ConfigEntryBase)SparrohPlugin.ToolbarFiltersCollapsed).ConfigFile.Save();
		}
	}

	private static void SyncToolbarFromConfig()
	{
		_suppressToolbarCallbacks = true;
		try
		{
			if (_sortDropdown != null)
			{
				int num = IndexOfSortMode(SparrohPlugin.ModSortMode?.Value);
				_sortDropdown.Select(num, false);
			}
			if (_hideEmptyToggle != null && SparrohPlugin.HideModsWithoutConfig != null)
			{
				_hideEmptyToggle.IsOn = SparrohPlugin.HideModsWithoutConfig.Value;
			}
			if (_groupByAuthorToggle != null && SparrohPlugin.GroupModsByAuthor != null)
			{
				_groupByAuthorToggle.IsOn = SparrohPlugin.GroupModsByAuthor.Value;
			}
			RefreshFilterChipStyles(NormalizeFilter(SparrohPlugin.ModListFilter?.Value));
			UpdateExpandCollapseAllLabel();
			bool flag = SparrohPlugin.ToolbarFiltersCollapsed?.Value ?? false;
			if (flag != _toolbarFiltersCollapsed)
			{
				SetToolbarFiltersCollapsed(flag, persist: false);
			}
			else
			{
				ApplyToolbarFiltersCollapsed(persist: false);
			}
		}
		finally
		{
			_suppressToolbarCallbacks = false;
		}
	}

	private static void ApplyFilterChip(string filterId)
	{
		filterId = NormalizeFilter(filterId);
		if (SparrohPlugin.ModListFilter != null && !string.Equals(SparrohPlugin.ModListFilter.Value, filterId, StringComparison.OrdinalIgnoreCase))
		{
			SparrohPlugin.ModListFilter.Value = filterId;
			((ConfigEntryBase)SparrohPlugin.ModListFilter).ConfigFile.Save();
		}
		RefreshFilterChipStyles(filterId);
		RefreshMods(resetScroll: true);
	}

	private static void RefreshFilterChipStyles(string activeFilter)
	{
		activeFilter = NormalizeFilter(activeFilter);
		for (int i = 0; i < _filterChipButtons.Count && i < FilterChipIds.Length; i++)
		{
			bool flag = string.Equals(FilterChipIds[i], activeFilter, StringComparison.OrdinalIgnoreCase);
			_filterChipButtons[i].SetStyle((UIButtonStyle)(flag ? 3 : 0));
		}
	}

	private static int IndexOfSortMode(string mode)
	{
		if (string.IsNullOrEmpty(mode))
		{
			return 0;
		}
		for (int i = 0; i < SortModeIds.Length; i++)
		{
			if (string.Equals(SortModeIds[i], mode, StringComparison.OrdinalIgnoreCase))
			{
				return i;
			}
		}
		return 0;
	}

	private static string NormalizeFilter(string filter)
	{
		if (string.IsNullOrEmpty(filter))
		{
			return "All";
		}
		for (int i = 0; i < FilterChipIds.Length; i++)
		{
			if (string.Equals(FilterChipIds[i], filter, StringComparison.OrdinalIgnoreCase))
			{
				return FilterChipIds[i];
			}
		}
		return "All";
	}

	private static string GetModKey(ModInfo mod)
	{
		if (!string.IsNullOrEmpty(((ModInfo)(ref mod)).GUID))
		{
			return ((ModInfo)(ref mod)).GUID;
		}
		return ((ModInfo)(ref mod)).Name ?? "";
	}

	private static string GetAuthorGroup(ModInfo mod)
	{
		string gUID = ((ModInfo)(ref mod)).GUID;
		if (string.IsNullOrEmpty(gUID))
		{
			return "Other";
		}
		int num = gUID.IndexOf('.');
		if (num <= 0)
		{
			return "Other";
		}
		return gUID.Substring(0, num);
	}

	private static void LoadCollapsedFromConfig()
	{
		_collapsedMods.Clear();
		string text = SparrohPlugin.CollapsedMods?.Value;
		if (string.IsNullOrWhiteSpace(text))
		{
			return;
		}
		string[] array = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			string text2 = array[i].Trim();
			if (text2.Length > 0)
			{
				_collapsedMods.Add(text2);
			}
		}
	}

	private static void SaveCollapsedToConfig()
	{
		if (SparrohPlugin.CollapsedMods != null)
		{
			string text = ((_collapsedMods.Count == 0) ? "" : string.Join(",", _collapsedMods));
			if (!(SparrohPlugin.CollapsedMods.Value == text))
			{
				SparrohPlugin.CollapsedMods.Value = text;
				((ConfigEntryBase)SparrohPlugin.CollapsedMods).ConfigFile.Save();
			}
		}
	}

	private static bool IsModExpanded(string key)
	{
		return !_collapsedMods.Contains(key);
	}

	private static void SetModExpanded(string key, bool expanded)
	{
		if (!string.IsNullOrEmpty(key))
		{
			if (expanded)
			{
				_collapsedMods.Remove(key);
			}
			else
			{
				_collapsedMods.Add(key);
			}
			SaveCollapsedToConfig();
		}
	}

	private static void ApplyBlockExpanded(ModBlockState block, bool expanded, bool persist)
	{
		if (block != null)
		{
			block.IsExpanded = expanded;
			if ((Object)(object)block.Body != (Object)null)
			{
				block.Body.SetActive(expanded);
			}
			if ((Object)(object)block.Chevron != (Object)null)
			{
				((TMP_Text)block.Chevron).text = (expanded ? "-" : "+");
			}
			if (persist)
			{
				SetModExpanded(block.Key, expanded);
			}
			SyncStickyTitleForBlock(block);
		}
	}

	private static string FormatStickyTitle(ModBlockState block)
	{
		if (block == null)
		{
			return "";
		}
		return (block.IsExpanded ? "- " : "+ ") + block.TitleRichText;
	}

	private static void SyncStickyTitleForBlock(ModBlockState block)
	{
		if (block != null && !((Object)(object)block.TitleRect == (Object)null))
		{
			_stickyTitles?.UpdateTitle(block.TitleRect, FormatStickyTitle(block));
		}
	}

	private static void ToggleModBlock(ModBlockState block)
	{
		if (block != null)
		{
			ClearActiveEditing();
			ApplyBlockExpanded(block, !block.IsExpanded, persist: true);
			_stickyTitles?.Refresh();
			UpdateExpandCollapseAllLabel();
		}
	}

	private static ModBlockState FindModBlock(string key)
	{
		if (string.IsNullOrEmpty(key))
		{
			return null;
		}
		for (int i = 0; i < _modBlocks.Count; i++)
		{
			ModBlockState modBlockState = _modBlocks[i];
			if (modBlockState != null && string.Equals(modBlockState.Key, key, StringComparison.OrdinalIgnoreCase))
			{
				return modBlockState;
			}
		}
		return null;
	}

	internal static void ToggleModBlockByKey(string key)
	{
		ToggleModBlock(FindModBlock(key));
	}

	private static void ToggleExpandCollapseAll()
	{
		bool flag = false;
		for (int i = 0; i < _modBlocks.Count; i++)
		{
			if (_modBlocks[i] != null && _modBlocks[i].IsExpanded)
			{
				flag = true;
				break;
			}
		}
		bool flag2 = !flag;
		for (int j = 0; j < _modBlocks.Count; j++)
		{
			ModBlockState modBlockState = _modBlocks[j];
			if (modBlockState != null)
			{
				ApplyBlockExpanded(modBlockState, flag2, persist: false);
				if (flag2)
				{
					_collapsedMods.Remove(modBlockState.Key);
				}
				else
				{
					_collapsedMods.Add(modBlockState.Key);
				}
			}
		}
		SaveCollapsedToConfig();
		UpdateExpandCollapseAllLabel();
		_stickyTitles?.Refresh();
	}

	private static void UpdateExpandCollapseAllLabel()
	{
		UIButton expandCollapseAllBtn = _expandCollapseAllBtn;
		if ((Object)(object)((expandCollapseAllBtn != null) ? expandCollapseAllBtn.Label : null) == (Object)null)
		{
			return;
		}
		bool flag = false;
		if (_modBlocks.Count == 0)
		{
			flag = _collapsedMods.Count == 0;
		}
		else
		{
			for (int i = 0; i < _modBlocks.Count; i++)
			{
				if (_modBlocks[i] != null && _modBlocks[i].IsExpanded)
				{
					flag = true;
					break;
				}
			}
		}
		_expandCollapseAllBtn.SetText(flag ? "Collapse all" : "Expand all");
	}

	private static void CreateGroupHeader(Transform parent, string groupName)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		Image val = UIFactory.CreateImage("Group_" + groupName, parent, UIColors.SectionBar, false);
		UIFactory.ApplyWhiteSprite(val);
		GameObject gameObject = ((Component)val).gameObject;
		float? num = UITheme.S(28f);
		float? num2 = UITheme.S(28f);
		UIHelpers.EnsureLayoutElement(gameObject, (float?)null, num, num2);
		string text = (string.IsNullOrEmpty(groupName) ? "Other" : groupName);
		UIHelpers.SetFillParent(((TMP_Text)UIFactory.CreateTmp("Text", (Transform)(object)((Graphic)val).rectTransform, RichText.Bold(text), UITheme.S(18f), (Color?)UIColors.TextSecondary, (TextAlignmentOptions)4097, false)).rectTransform, UITheme.S(8f));
	}

	private static StickyModTitleController CreateStickyModTitleOverlay(UIScrollView scrollView)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		float num = UITheme.S(44f);
		Image obj = UIFactory.CreateImage("StickyModTitle", (Transform)(object)scrollView.Viewport, UIColors.TitleBar, true);
		UIFactory.ApplyWhiteSprite(obj);
		RectTransform rectTransform = ((Graphic)obj).rectTransform;
		UIHelpers.SetTopStretch(rectTransform, num, 0f, 0f, 0f);
		((Transform)rectTransform).SetAsLastSibling();
		Image obj2 = UIFactory.CreateImage("Accent", (Transform)(object)rectTransform, UIColors.BorderAccent, false);
		UIFactory.ApplyWhiteSprite(obj2);
		RectTransform rectTransform2 = ((Graphic)obj2).rectTransform;
		rectTransform2.anchorMin = new Vector2(0f, 0f);
		rectTransform2.anchorMax = new Vector2(1f, 0f);
		rectTransform2.pivot = new Vector2(0.5f, 0f);
		rectTransform2.sizeDelta = new Vector2(0f, UITheme.S(2f));
		rectTransform2.anchoredPosition = Vector2.zero;
		TextMeshProUGUI val = UIFactory.CreateTmp("Text", (Transform)(object)rectTransform, "", UITheme.S(22f), (Color?)UIColors.TextPrimary, (TextAlignmentOptions)4097, false);
		((TMP_Text)val).fontStyle = (FontStyles)1;
		((Graphic)val).raycastTarget = false;
		UIHelpers.SetFillParent(((TMP_Text)val).rectTransform, UITheme.S(10f));
		((Component)obj).gameObject.SetActive(false);
		StickyModTitleController controller = scrollView.GameObject.AddComponent<StickyModTitleController>();
		controller.Initialize(scrollView.ScrollRect, rectTransform, val, num);
		((Component)obj).gameObject.AddComponent<ClickVsDragToggle>().Initialize(initialValue: true, 8f, delegate
		{
			controller.ToggleActiveMod();
		});
		return controller;
	}

	public static void RefreshMods()
	{
		RefreshMods(resetScroll: false);
	}

	public static void RefreshMods(bool resetScroll, bool preserveSearchFocus = false)
	{
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0221: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_028b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		if (_window == null || (Object)(object)_window.Content == (Object)null)
		{
			return;
		}
		if (preserveSearchFocus)
		{
			for (int num = _openDropdowns.Count - 1; num >= 0; num--)
			{
				UIDropdown val = _openDropdowns[num];
				if (val != null)
				{
					val.CloseList();
				}
			}
			_openDropdowns.Clear();
		}
		else
		{
			ClearActiveEditing();
		}
		_stickyTitles?.Clear();
		_modBlocks.Clear();
		UIHelpers.DestroyChildren(_window.Content);
		_cfgFilesCache = null;
		LoadCollapsedFromConfig();
		try
		{
			IReadOnlyList<ModInfo> mods = ModManager.Mods;
			if (mods == null)
			{
				ShowEmptyState("No mods loaded");
				_stickyTitles?.Refresh();
				UpdateExpandCollapseAllLabel();
				if (resetScroll)
				{
					ResetScrollToTop();
				}
				return;
			}
			List<ModInfo> list = BuildVisibleMods(mods);
			if (list.Count == 0)
			{
				ShowEmptyState("No mods match");
				_stickyTitles?.Refresh();
				UpdateExpandCollapseAllLabel();
				if (resetScroll)
				{
					ResetScrollToTop();
				}
				if (preserveSearchFocus)
				{
					RestoreSearchFocus();
				}
				return;
			}
			bool num2 = SparrohPlugin.GroupModsByAuthor?.Value ?? false;
			bool flag = true;
			if (num2)
			{
				SortedDictionary<string, List<ModInfo>> sortedDictionary = new SortedDictionary<string, List<ModInfo>>(StringComparer.OrdinalIgnoreCase);
				for (int i = 0; i < list.Count; i++)
				{
					string authorGroup = GetAuthorGroup(list[i]);
					if (!sortedDictionary.TryGetValue(authorGroup, out var value))
					{
						value = (sortedDictionary[authorGroup] = new List<ModInfo>());
					}
					value.Add(list[i]);
				}
				foreach (KeyValuePair<string, List<ModInfo>> item in sortedDictionary)
				{
					if (!flag)
					{
						UISeparator.Create(_window.Content, "Separator", true);
					}
					flag = false;
					CreateGroupHeader(_window.Content, item.Key);
					for (int j = 0; j < item.Value.Count; j++)
					{
						try
						{
							if (j > 0)
							{
								UISeparator.Create(_window.Content, "Separator", true);
							}
							CreateModConfig(item.Value[j], _window.Content);
						}
						catch (Exception ex)
						{
							ManualLogSource logger = SparrohPlugin.Logger;
							ModInfo val2 = item.Value[j];
							logger.LogError((object)("Error creating config for mod " + ((ModInfo)(ref val2)).Name + ": " + ex.Message));
						}
					}
				}
			}
			else
			{
				foreach (ModInfo item2 in list)
				{
					ModInfo current2 = item2;
					try
					{
						if (!flag)
						{
							UISeparator.Create(_window.Content, "Separator", true);
						}
						flag = false;
						CreateModConfig(current2, _window.Content);
					}
					catch (Exception ex2)
					{
						SparrohPlugin.Logger.LogError((object)("Error creating config for mod " + ((ModInfo)(ref current2)).Name + ": " + ex2.Message));
					}
				}
			}
		}
		catch (Exception ex3)
		{
			SparrohPlugin.Logger.LogError((object)("Error refreshing mods list: " + ex3.Message));
		}
		_stickyTitles?.Refresh();
		UpdateExpandCollapseAllLabel();
		if (resetScroll)
		{
			ResetScrollToTop();
		}
		if (preserveSearchFocus)
		{
			RestoreSearchFocus();
		}
	}

	private static void ShowEmptyState(string message)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		GameObject gameObject = UIText.Create(_window.Content, "EmptyState", message, UITheme.S(16f), (Color?)UIColors.TextMuted, (TextAlignmentOptions)514, false).GameObject;
		float? num = UITheme.S(48f);
		float? num2 = UITheme.S(48f);
		UIHelpers.EnsureLayoutElement(gameObject, (float?)null, num, num2);
	}

	private static void ResetScrollToTop()
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		UIWindow window = _window;
		object obj;
		if (window == null)
		{
			obj = null;
		}
		else
		{
			UIScrollView scrollView = window.ScrollView;
			obj = ((scrollView != null) ? scrollView.ScrollRect : null);
		}
		if (!((Object)obj == (Object)null))
		{
			ScrollRect scrollRect = _window.ScrollView.ScrollRect;
			scrollRect.velocity = Vector2.zero;
			scrollRect.verticalNormalizedPosition = 1f;
		}
	}

	private static void RestoreSearchFocus()
	{
		UIInputField searchField = _searchField;
		if (!((Object)(object)((searchField != null) ? searchField.Input : null) == (Object)null))
		{
			_activeInput = _searchField.Input;
			_searchField.Input.ActivateInputField();
			if ((Object)(object)EventSystem.current != (Object)null)
			{
				EventSystem.current.SetSelectedGameObject(((Component)_searchField.Input).gameObject);
			}
		}
	}

	private static List<ModInfo> BuildVisibleMods(IReadOnlyList<ModInfo> source)
	{
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: 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)
		string query = (_searchQuery ?? "").Trim();
		bool flag = SparrohPlugin.HideModsWithoutConfig?.Value ?? true;
		string text = NormalizeFilter(SparrohPlugin.ModListFilter?.Value);
		string mode = SparrohPlugin.ModSortMode?.Value ?? "Alphabetical";
		List<ModInfo> list = new List<ModInfo>(source.Count);
		for (int i = 0; i < source.Count; i++)
		{
			ModInfo val = source[i];
			if (ModMatchesSearch(val, query) && (!(text == "Sandbox") || ((ModInfo)(ref val)).IsSandbox) && (!(text == "ClientSide") || ((ModInfo)(ref val)).IsClientSide) && (!flag || ModHasConfig(val)))
			{
				list.Add(val);
			}
		}
		SortMods(list, mode);
		return list;
	}

	private static bool ModMatchesSearch(ModInfo mod, string query)
	{
		if (string.IsNullOrEmpty(query))
		{
			return true;
		}
		if (!string.IsNullOrEmpty(((ModInfo)(ref mod)).Name) && ((ModInfo)(ref mod)).Name.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		if (!string.IsNullOrEmpty(((ModInfo)(ref mod)).GUID) && ((ModInfo)(ref mod)).GUID.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0)
		{
			return true;
		}
		return false;
	}

	private static void SortMods(List<ModInfo> list, string mode)
	{
		if (list == null || list.Count <= 1)
		{
			return;
		}
		mode = mode ?? "Alphabetical";
		if (string.Equals(mode, "LoadOrder", StringComparison.OrdinalIgnoreCase))
		{
			return;
		}
		if (string.Equals(mode, "AlphabeticalDesc", StringComparison.OrdinalIgnoreCase))
		{
			list.Sort((ModInfo a, ModInfo b) => string.Compare(((ModInfo)(ref b)).Name, ((ModInfo)(ref a)).Name, StringComparison.OrdinalIgnoreCase));
		}
		else if (string.Equals(mode, "SandboxFirst", StringComparison.OrdinalIgnoreCase))
		{
			list.Sort(delegate(ModInfo a, ModInfo b)
			{
				int num = ((ModInfo)(ref b)).IsSandbox.CompareTo(((ModInfo)(ref a)).IsSandbox);
				return (num != 0) ? num : string.Compare(((ModInfo)(ref a)).Name, ((ModInfo)(ref b)).Name, StringComparison.OrdinalIgnoreCase);
			});
		}
		else if (string.Equals(mode, "HasConfigFirst", StringComparison.OrdinalIgnoreCase))
		{
			list.Sort(delegate(ModInfo a, ModInfo b)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				bool value = ModHasConfig(a);
				int num = ModHasConfig(b).CompareTo(value);
				return (num != 0) ? num : string.Compare(((ModInfo)(ref a)).Name, ((ModInfo)(ref b)).Name, StringComparison.OrdinalIgnoreCase);
			});
		}
		else
		{
			list.Sort((ModInfo a, ModInfo b) => string.Compare(((ModInfo)(ref a)).Name, ((ModInfo)(ref b)).Name, StringComparison.OrdinalIgnoreCase));
		}
	}

	private static string[] GetCfgFiles()
	{
		if (_cfgFilesCache != null)
		{
			return _cfgFilesCache;
		}
		try
		{
			if (Directory.Exists(Paths.ConfigPath))
			{
				_cfgFilesCache = Directory.GetFiles(Paths.ConfigPath, "*.cfg");
			}
			else
			{
				_cfgFilesCache = Array.Empty<string>();
			}
		}
		catch (Exception ex)
		{
			SparrohPlugin.Logger.LogWarning((object)("Could not enumerate config files: " + ex.Message));
			_cfgFilesCache = Array.Empty<string>();
		}
		return _cfgFilesCache;
	}

	private static bool TryFindConfigPath(ModInfo mod, out string configPath)
	{
		configPath = null;
		if (string.IsNullOrEmpty(((ModInfo)(ref mod)).Name))
		{
			return false;
		}
		string value = ((ModInfo)(ref mod)).Name.ToLowerInvariant();
		string[] cfgFiles = GetCfgFiles();
		foreach (string text in cfgFiles)
		{
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
			if (fileNameWithoutExtension != null && fileNameWithoutExtension.ToLowerInvariant().Contains(value))
			{
				configPath = text;
				return true;
			}
		}
		return false;
	}

	private static bool ModHasConfig(ModInfo mod)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		string configPath;
		return TryFindConfigPath(mod, out configPath);
	}

	private static void ApplySettingValue(ModInfo mod, string configPath, string section, string key, string value, ConfigEntry<string> fileFallback)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		if (!TrySetLiveConfigValue(mod, configPath, section, key, value) && fileFallback != null)
		{
			fileFallback.Value = value ?? "";
			((ConfigEntryBase)fileFallback).ConfigFile.Save();
		}
	}

	private static bool TrySetLiveConfigValue(ModInfo mod, string configPath, string section, string key, string value)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			BaseUnityPlugin val = FindPluginForConfig(mod, configPath);
			if (((val != null) ? val.Config : null) == null)
			{
				return false;
			}
			ConfigEntryBase val2 = FindLiveEntry(val.Config, section, key);
			if (val2 == null)
			{
				return false;
			}
			val2.SetSerializedValue(value ?? "");
			val.Config.Save();
			return true;
		}
		catch (Exception ex)
		{
			SparrohPlugin.Logger.LogWarning((object)("Live config set failed for [" + section + "] " + key + ": " + ex.Message));
			return false;
		}
	}

	private static BaseUnityPlugin FindPluginForConfig(ModInfo mod, string configPath)
	{
		if (!string.IsNullOrEmpty(((ModInfo)(ref mod)).GUID) && Chainloader.PluginInfos != null && Chainloader.PluginInfos.TryGetValue(((ModInfo)(ref mod)).GUID, out var value))
		{
			BaseUnityPlugin val = ((value != null) ? value.Instance : null);
			if (val != null)
			{
				return val;
			}
		}
		if (Chainloader.PluginInfos == null || string.IsNullOrEmpty(configPath))
		{
			return null;
		}
		foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
		{
			PluginInfo value2 = pluginInfo.Value;
			BaseUnityPlugin val2 = ((value2 != null) ? value2.Instance : null);
			if (val2 != null && val2.Config != null)
			{
				string configFilePath = val2.Config.ConfigFilePath;
				if (!string.IsNullOrEmpty(configFilePath) && string.Equals(configFilePath, configPath, StringComparison.OrdinalIgnoreCase))
				{
					return val2;
				}
			}
		}
		return null;
	}

	private static ConfigEntryBase FindLiveEntry(ConfigFile config, string section, string key)
	{
		if (config == null || string.IsNullOrEmpty(section) || string.IsNullOrEmpty(key))
		{
			return null;
		}
		foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in config)
		{
			if (!(item.Key == (ConfigDefinition)null) && item.Value != null && string.Equals(item.Key.Section, section, StringComparison.OrdinalIgnoreCase) && string.Equals(item.Key.Key, key, StringComparison.OrdinalIgnoreCase))
			{
				return item.Value;
			}
		}
		return null;
	}

	private static string GetLiveOrFileValue(ModInfo mod, string configPath, string section, string key, string fileValue)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			BaseUnityPlugin val = FindPluginForConfig(mod, configPath);
			ConfigEntryBase val2 = (((Object)(object)val != (Object)null) ? FindLiveEntry(val.Config, section, key) : null);
			if (val2 != null)
			{
				string serializedValue = val2.GetSerializedValue();
				if (serializedValue != null)
				{
					return serializedValue;
				}
			}
		}
		catch
		{
		}
		return fileValue ?? "";
	}

	private static Dictionary<string, List<(string entry, string[] options)>> ParseModConfig(string configPath)
	{
		try
		{
			Dictionary<string, List<(string, string[])>> dictionary = new Dictionary<string, List<(string, string[])>>();
			string key = "";
			List<string> list = new List<string>();
			foreach (string item2 in File.ReadLines(configPath))
			{
				if (string.IsNullOrWhiteSpace(item2))
				{
					continue;
				}
				if (item2.StartsWith("#"))
				{
					list.Add(item2.TrimStart('#').Trim());
				}
				else if (item2.StartsWith("[") && item2.EndsWith("]"))
				{
					key = item2.Trim();
					if (!dictionary.ContainsKey(key))
					{
						dictionary[key] = new List<(string, string[])>();
					}
					list.Clear();
				}
				else
				{
					if (!item2.Contains("="))
					{
						continue;
					}
					if (!dictionary.ContainsKey(key))
					{
						dictionary[key] = new List<(string, string[])>();
					}
					string[] item = null;
					foreach (string item3 in list)
					{
						if (item3.StartsWith("Acceptable values:"))
						{
							item = (from s in item3.Substring("Acceptable values:".Length).Split(',')
								select s.Trim()).ToArray();
							break;
						}
					}
					dictionary[key].Add((item2.Trim(), item));
					list.Clear();
				}
			}
			return dictionary;
		}
		catch (Exception ex)
		{
			SparrohPlugin.Logger.LogError((object)("Error parsing config file '" + configPath + "': " + ex.Message));
			return new Dictionary<string, List<(string, string[])>>();
		}
	}

	private static void CreateModConfig(ModInfo mod, Transform parent)
	{
		//IL_0007: 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_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Expected O, but got Unknown
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0275: Unknown result type (might be due to invalid IL or missing references)
		//IL_0284: Expected O, but got Unknown
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_033f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0374: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d7: Expected O, but got Unknown
		//IL_0646: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0765: Unknown result type (might be due to invalid IL or missing references)
		//IL_08af: Unknown result type (might be due to invalid IL or missing references)
		//IL_08a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a4b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a55: Expected O, but got Unknown
		//IL_091d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0916: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b7b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c24: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c29: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c2b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c32: Expected O, but got Unknown
		try
		{
			ModInfo modLocal = mod;
			string modKey = GetModKey(modLocal);
			bool flag = IsModExpanded(modKey);
			RectTransform val = UIFactory.CreateRect("ModBlock_" + ((ModInfo)(ref modLocal)).Name, parent);
			UIFactory.AddVerticalLayout(((Component)val).gameObject, UITheme.S(UITheme.SpacingTight), new RectOffset(0, 0, 0, 0), (TextAnchor)0, true, false, true, true);
			UIFactory.AddContentSizeFitter(((Component)val).gameObject, (FitMode)0, (FitMode)2);
			Image val2 = UIFactory.CreateImage(((ModInfo)(ref modLocal)).Name + " Title", (Transform)(object)val, UIColors.TitleBar, true);
			UIFactory.ApplyWhiteSprite(val2);
			GameObject gameObject = ((Component)val2).gameObject;
			float? num = UITheme.S(44f);
			float? num2 = UITheme.S(44f);
			UIHelpers.EnsureLayoutElement(gameObject, (float?)null, num, num2);
			UIFactory.AddHorizontalLayout(((Component)val2).gameObject, UITheme.S(6f), UITheme.ScaledPadding(10, 10, 4, 4), (TextAnchor)3, true, false, true, true);
			TextMeshProUGUI val3 = UIFactory.CreateTmp("Chevron", (Transform)(object)((Graphic)val2).rectTransform, flag ? "-" : "+", UITheme.S(22f), (Color?)UIColors.TextSecondary, (TextAlignmentOptions)514, false);
			((TMP_Text)val3).fontStyle = (FontStyles)1;
			((Graphic)val3).raycastTarget = false;
			UIHelpers.EnsureLayoutElement(((Component)val3).gameObject, (float?)UITheme.S(28f), (float?)UITheme.S(36f), (float?)null).flexibleWidth = 0f;
			string text = RichText.Bold(((ModInfo)(ref modLocal)).Name);
			if (((ModInfo)(ref modLocal)).IsSandbox)
			{
				text = text + " " + RichText.Size("[" + RichText.Italic(RichText.Colorize("Sandbox", UIColors.Rose)) + "]", 55);
			}
			TextMeshProUGUI obj = UIFactory.CreateTmp("Text", (Transform)(object)((Graphic)val2).rectTransform, text, UITheme.S(22f), (Color?)UIColors.TextPrimary, (TextAlignmentOptions)4097, false);
			((TMP_Text)obj).fontStyle = (FontStyles)1;
			((Graphic)obj).raycastTarget = false;
			GameObject gameObject2 = ((Component)obj).gameObject;
			num2 = UITheme.S(36f);
			UIHelpers.EnsureLayoutElement(gameObject2, (float?)null, num2, (float?)null).flexibleWidth = 1f;
			RectTransform val4 = UIFactory.CreateRect("Body", (Transform)(object)val);
			UIFactory.AddVerticalLayout(((Component)val4).gameObject, UITheme.S(UITheme.SpacingTight), new RectOffset(0, 0, 0, 0), (TextAnchor)0, true, false, true, true);
			UIFactory.AddContentSizeFitter(((Component)val4).gameObject, (FitMode)0, (FitMode)2);
			((Component)val4).gameObject.SetActive(flag);
			ModBlockState blockState = new ModBlockState
			{
				Key = modKey,
				Body = ((Component)val4).gameObject,
				Chevron = val3,
				TitleRect = ((Graphic)val2).rectTransform,
				TitleRichText = text,
				IsExpanded = flag
			};
			_modBlocks.Add(blockState);
			_stickyTitles?.Register(((Graphic)val2).r