Decompiled source of SonicPickupFilters v0.1.0

SonicPickupFilters.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
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("SonicPickupFilters")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+45fa2e7778d4f902d8abdef9dceea0c84bb38e66")]
[assembly: AssemblyProduct("SonicPickupFilters")]
[assembly: AssemblyTitle("SonicPickupFilters")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SonicPickupFilters
{
	[HarmonyPatch(typeof(Player), "AutoPickup")]
	internal static class AutoPickupPatches
	{
		private enum CapDecision
		{
			Allow,
			Suppress,
			Skip
		}

		private static readonly List<ItemDrop> Suppressed = new List<ItemDrop>(64);

		private static readonly Dictionary<string, int> PendingPickup = new Dictionary<string, int>(StringComparer.Ordinal);

		private static Collider[] _overlapBuffer = (Collider[])(object)new Collider[128];

		private static readonly FieldInfo AutoPickupMaskField = AccessTools.Field(typeof(Player), "m_autoPickupMask");

		private static float _nextSummaryLog;

		private static float _nextFailLog;

		private static int _passSeq;

		private static int _failLogs;

		private static string _step = "init";

		private static string _item = "-";

		internal static void ResetRuntimeState()
		{
			try
			{
				RestoreSuppressed();
			}
			catch
			{
				Suppressed.Clear();
			}
			PendingPickup.Clear();
			_step = "reset";
			_item = "-";
		}

		internal static string DumpNearby(Player player)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Expected O, but got Unknown
			//IL_00f3: 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_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Expected O, but got Unknown
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Expected O, but got Unknown
			StringBuilder stringBuilder = new StringBuilder(1024);
			stringBuilder.AppendLine("=== spf_dump ===");
			stringBuilder.AppendLine("rules=" + PickupRuleStore.FormatRulesSnapshot());
			stringBuilder.AppendLine("enabled=" + SonicPickupFiltersPlugin.IsModEnabled() + " debug=" + SonicPickupFiltersPlugin.DebugEnabled);
			if ((Object)player == (Object)null)
			{
				stringBuilder.AppendLine("player=null");
				return stringBuilder.ToString();
			}
			string how;
			object obj = TryGetInventoryObject(player, out how);
			stringBuilder.AppendLine("inventory=" + ((obj != null) ? "ok" : "null") + " via=" + how);
			Vector3 val = ((Component)player).transform.position + Vector3.up * 0.5f;
			float autoPickupRange = player.m_autoPickupRange;
			int num = ResolveMask(player);
			int num2 = ((num >= 0) ? Physics.OverlapSphereNonAlloc(val, autoPickupRange, _overlapBuffer, num) : Physics.OverlapSphereNonAlloc(val, autoPickupRange, _overlapBuffer));
			stringBuilder.AppendLine($"range={autoPickupRange:0.##} mask={num} hits={num2}");
			int num3 = 0;
			for (int i = 0; i < num2; i++)
			{
				Collider val2 = _overlapBuffer[i];
				if ((Object)val2 == (Object)null)
				{
					continue;
				}
				ItemDrop val3 = null;
				string text = "?";
				try
				{
					text = ((Object)((Component)val2).gameObject).name;
					val3 = ((Component)val2).GetComponent<ItemDrop>();
					if ((Object)val3 == (Object)null && (Object)val2.attachedRigidbody != (Object)null)
					{
						val3 = ((Component)val2.attachedRigidbody).GetComponent<ItemDrop>() ?? ((Component)val2.attachedRigidbody).GetComponentInParent<ItemDrop>();
					}
				}
				catch (Exception ex)
				{
					stringBuilder.AppendLine($"  hit[{i}] col='{text}' GetItemDrop FAIL {ex.GetType().Name}: {ex.Message}");
					continue;
				}
				if (!((Object)val3 == (Object)null))
				{
					num3++;
					string text2;
					try
					{
						text2 = ((Object)((Component)val3).gameObject).name;
					}
					catch
					{
						text2 = text;
					}
					string text3 = PickupRuleStore.NormalizePrefabName(text2);
					PickupRule rule = PickupRuleStore.GetRule(text3);
					string text4 = TryShared(val3, text3);
					int num4 = TryStack(val3, text3);
					int num5 = TryMaxStack(val3, text3);
					bool flag = false;
					try
					{
						flag = val3.m_autoPickup;
					}
					catch (Exception ex2)
					{
						stringBuilder.AppendLine("  " + text3 + " m_autoPickup FAIL " + ex2.GetType().Name + ": " + ex2.Message);
						continue;
					}
					string text5 = "-";
					if (!string.IsNullOrEmpty(text4) && obj != null)
					{
						text5 = CountHaveReflect(obj, text4, text3, out var method) + " via " + method;
					}
					stringBuilder.AppendLine($"  {text3} raw='{text2}' rule={FormatRule(rule)} auto={flag} " + $"shared='{text4}' stack={num4} max={num5} invHave={text5}");
				}
			}
			stringBuilder.AppendLine("dropsListed=" + num3);
			return stringBuilder.ToString();
		}

		[HarmonyPrefix]
		private static void Prefix(Player __instance, float dt)
		{
			_step = "Prefix.enter";
			_item = "-";
			try
			{
				RunPrefix(__instance);
				_step = "Prefix.done";
			}
			catch (Exception ex)
			{
				Fail("Prefix.uncaught", ex);
				try
				{
					RestoreSuppressed();
				}
				catch (Exception ex2)
				{
					Fail("Prefix.restoreAfterFail", ex2);
					Suppressed.Clear();
				}
				PendingPickup.Clear();
			}
		}

		private static void RunPrefix(Player __instance)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0056: 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_006a: Expected O, but got Unknown
			//IL_006a: Expected O, but got Unknown
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Expected O, but got Unknown
			//IL_007d: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			_step = "RestoreSuppressed";
			RestoreSuppressed();
			PendingPickup.Clear();
			_step = "IsModEnabled";
			if (!SonicPickupFiltersPlugin.IsModEnabled())
			{
				return;
			}
			_step = "LocalPlayerCheck";
			if ((Object)__instance == (Object)null || (Object)Player.m_localPlayer == (Object)null || (Object)__instance != (Object)Player.m_localPlayer)
			{
				return;
			}
			_step = "ReadRange";
			Vector3 val = ((Component)__instance).transform.position + Vector3.up * 0.5f;
			float autoPickupRange = __instance.m_autoPickupRange;
			_step = "ResolveMask";
			int num = ResolveMask(__instance);
			_step = "OverlapSphere";
			_item = $"range={autoPickupRange:0.##} mask={num}";
			int num2 = ((num >= 0) ? Physics.OverlapSphereNonAlloc(val, autoPickupRange, _overlapBuffer, num) : Physics.OverlapSphereNonAlloc(val, autoPickupRange, _overlapBuffer));
			if (num2 >= _overlapBuffer.Length)
			{
				_step = "GrowOverlapBuffer";
				Collider[] array = (Collider[])(object)new Collider[_overlapBuffer.Length * 2];
				Array.Copy(_overlapBuffer, array, _overlapBuffer.Length);
				_overlapBuffer = array;
				num2 = ((num >= 0) ? Physics.OverlapSphereNonAlloc(val, autoPickupRange, _overlapBuffer, num) : Physics.OverlapSphereNonAlloc(val, autoPickupRange, _overlapBuffer));
			}
			_passSeq++;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			int num6 = 0;
			int num7 = 0;
			int num8 = 0;
			int num9 = 0;
			int errors = 0;
			bool flag = false;
			object obj = null;
			bool flag2 = false;
			string how = "not-needed";
			for (int i = 0; i < num2; i++)
			{
				_step = "Loop.collider";
				_item = $"hit[{i}/{num2}]";
				Collider val2 = _overlapBuffer[i];
				if ((Object)val2 == (Object)null)
				{
					continue;
				}
				string text = "?";
				try
				{
					_step = "Loop.colliderName";
					text = (_item = ((Object)((Component)val2).gameObject).name);
				}
				catch (Exception ex)
				{
					errors++;
					Fail("Loop.colliderName", ex);
					continue;
				}
				_step = "Loop.GetItemDrop";
				_item = text;
				ItemDrop val3 = TryGetItemDrop(val2, text, ref errors);
				if ((Object)val3 == (Object)null)
				{
					continue;
				}
				num3++;
				string text2 = text;
				try
				{
					_step = "Loop.dropGameObjectName";
					text2 = (_item = ((Object)((Component)val3).gameObject).name);
				}
				catch (Exception ex2)
				{
					errors++;
					Fail("Loop.dropGameObjectName item=" + text, ex2);
					continue;
				}
				string text3 = PickupRuleStore.NormalizePrefabName(text2);
				_item = text3 + " raw=" + text2;
				bool autoPickup;
				try
				{
					_step = "Loop.read_m_autoPickup";
					autoPickup = val3.m_autoPickup;
				}
				catch (Exception ex3)
				{
					errors++;
					Fail("Loop.read_m_autoPickup", ex3);
					continue;
				}
				if (!autoPickup)
				{
					num9++;
					continue;
				}
				PickupRule rule = PickupRuleStore.GetRule(text3);
				if (rule.Mode == PickupRuleMode.Allow)
				{
					num4++;
					continue;
				}
				flag = true;
				if (rule.Mode == PickupRuleMode.Block)
				{
					_step = "Block.suppress";
					_item = text3;
					Suppress(val3, text3);
					num5++;
					continue;
				}
				if (!flag2)
				{
					flag2 = true;
					obj = TryGetInventoryObject(__instance, out how);
				}
				_step = "Cap.enter";
				_item = text3;
				if (obj == null)
				{
					Log("Cap SUPPRESS prefab='" + text3 + "' reason=no-inventory (" + how + ")");
					Suppress(val3, text3);
					num7++;
					continue;
				}
				switch (ApplyCap(obj, val3, text3, text2, rule.Cap))
				{
				case CapDecision.Allow:
					num6++;
					break;
				case CapDecision.Suppress:
					num7++;
					break;
				default:
					num8++;
					break;
				}
			}
			_step = "Summary";
			_item = "-";
			if (SonicPickupFiltersPlugin.DebugEnabled && Time.unscaledTime >= _nextSummaryLog && (flag || num3 > 0))
			{
				_nextSummaryLog = Time.unscaledTime + 2f;
				Log($"SUMMARY hits={num2} drops={num3} allow={num4} block={num5} " + $"capAllow={num6} capSuppress={num7} capSkip={num8} " + $"alreadyOff={num9} errors={errors} suppressed={Suppressed.Count} " + "inv=" + how + " rules=" + PickupRuleStore.FormatRulesSnapshot());
			}
		}

		private static string FormatRule(PickupRule rule)
		{
			if (rule.Mode == PickupRuleMode.Block)
			{
				return "Block";
			}
			if (rule.Mode == PickupRuleMode.Cap)
			{
				return "Cap:" + rule.Cap;
			}
			return "Allow";
		}

		private static object TryGetInventoryObject(object player, out string how)
		{
			if (player == null)
			{
				how = "player-null";
				return null;
			}
			try
			{
				_step = "inv.RuntimeGetInventory";
				Type type = player.GetType();
				MethodInfo method = type.GetMethod("GetInventory", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (method != null)
				{
					object result = method.Invoke(player, null);
					how = "RuntimeGetInventory";
					return result;
				}
				how = "GetInventory-missing";
			}
			catch (TargetInvocationException ex)
			{
				how = "GetInventory-threw";
				Fail("inv.RuntimeGetInventory", ex.InnerException ?? ex);
			}
			catch (Exception ex2)
			{
				how = "GetInventory-threw";
				Fail("inv.RuntimeGetInventory", ex2);
			}
			try
			{
				_step = "inv.RuntimeField";
				Type type2 = player.GetType();
				while (type2 != null)
				{
					FieldInfo field = type2.GetField("m_inventory", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null)
					{
						object value = field.GetValue(player);
						how = "RuntimeField:" + type2.Name + " type=" + ((value == null) ? "null" : value.GetType().FullName);
						return value;
					}
					type2 = type2.BaseType;
				}
				how += "+no-m_inventory-field";
			}
			catch (Exception ex3)
			{
				Fail("inv.RuntimeField", ex3);
				how += "+field-threw";
			}
			return null;
		}

		private static int ResolveMask(Player player)
		{
			if (AutoPickupMaskField == null)
			{
				return -1;
			}
			try
			{
				object value = AutoPickupMaskField.GetValue(player);
				if (value is int)
				{
					return (int)value;
				}
				Log("m_autoPickupMask unexpected type=" + ((value == null) ? "null" : value.GetType().FullName));
			}
			catch (Exception ex)
			{
				Fail("ResolveMask", ex);
			}
			return -1;
		}

		private static ItemDrop TryGetItemDrop(Collider col, string colName, ref int errors)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			try
			{
				_step = "GetComponent<ItemDrop>";
				_item = colName;
				ItemDrop component = ((Component)col).GetComponent<ItemDrop>();
				if ((Object)component != (Object)null)
				{
					return component;
				}
				_step = "attachedRigidbody";
				Rigidbody attachedRigidbody = col.attachedRigidbody;
				if ((Object)attachedRigidbody == (Object)null)
				{
					return null;
				}
				_step = "rb.GetComponent<ItemDrop>";
				component = ((Component)attachedRigidbody).GetComponent<ItemDrop>();
				if ((Object)component != (Object)null)
				{
					return component;
				}
				_step = "rb.GetComponentInParent<ItemDrop>";
				return ((Component)attachedRigidbody).GetComponentInParent<ItemDrop>();
			}
			catch (Exception ex)
			{
				errors++;
				Fail("TryGetItemDrop", ex);
				return null;
			}
		}

		private static CapDecision ApplyCap(object inventory, ItemDrop drop, string prefab, string rawName, int cap)
		{
			_step = "Cap.TryShared";
			_item = prefab;
			string text = TryShared(drop, prefab);
			_step = "Cap.TryStack";
			int num = TryStack(drop, prefab);
			_step = "Cap.TryMaxStack";
			int num2 = TryMaxStack(drop, prefab);
			if (string.IsNullOrEmpty(text) || num < 1)
			{
				Log($"Cap SKIP prefab='{prefab}' raw='{rawName}' shared='{text}' stack={num} maxStack={num2}");
				return CapDecision.Skip;
			}
			_step = "Cap.CountHave";
			_item = prefab + " shared=" + text;
			string method;
			int num3 = CountHaveReflect(inventory, text, prefab, out method);
			PendingPickup.TryGetValue(text, out var value);
			int num4 = cap - num3 - value;
			if (num4 <= 0)
			{
				Suppress(drop, prefab);
				return CapDecision.Suppress;
			}
			int num5 = num;
			if (num > num4)
			{
				if (!TryCapShrink(drop, prefab, num4, num - num4))
				{
					Log($"Cap SUPPRESS prefab='{prefab}' reason=stack({num})>rem({num4}) shrink-failed");
					Suppress(drop, prefab);
					return CapDecision.Suppress;
				}
				num5 = num4;
				Log($"Cap SHRINK prefab='{prefab}' take={num5} leftOnGround={num - num4}");
			}
			PendingPickup[text] = value + num5;
			Log($"Cap ALLOW prefab='{prefab}' take={num5} have={num3} via={method}");
			return CapDecision.Allow;
		}

		private static bool TryCapShrink(ItemDrop drop, string prefab, int take, int leave)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			if (take < 1)
			{
				return false;
			}
			try
			{
				_step = "Cap.SetStack";
				if (drop.m_itemData != null)
				{
					drop.m_itemData.m_stack = take;
				}
				drop.SetStack(take);
			}
			catch (Exception ex)
			{
				Fail("Cap.SetStack", ex);
				return false;
			}
			if (leave < 1)
			{
				return true;
			}
			if ((Object)ObjectDB.instance == (Object)null)
			{
				Log("Cap shrink: ObjectDB null — took " + take + ", lost leave " + leave);
				return true;
			}
			try
			{
				_step = "Cap.InstantiateLeftover";
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefab);
				if ((Object)itemPrefab == (Object)null)
				{
					Log("Cap shrink: no prefab '" + prefab + "' — took " + take + ", lost leave " + leave);
					return true;
				}
				Vector3 val = ((Component)drop).transform.position + Vector3.up * 0.05f;
				Quaternion rotation = ((Component)drop).transform.rotation;
				GameObject val2 = Object.Instantiate<GameObject>(itemPrefab, val, rotation);
				ItemDrop component = val2.GetComponent<ItemDrop>();
				if ((Object)component != (Object)null)
				{
					if (component.m_itemData != null)
					{
						component.m_itemData.m_stack = leave;
					}
					try
					{
						component.SetStack(leave);
					}
					catch (Exception ex2)
					{
						Fail("Cap.leftover.SetStack", ex2);
					}
					component.m_autoPickup = false;
					component.m_autoPickup = true;
				}
				return true;
			}
			catch (Exception ex3)
			{
				Fail("Cap.InstantiateLeftover", ex3);
				return true;
			}
		}

		private static int CountHaveReflect(object inventory, string shared, string prefab, out string method)
		{
			if (inventory == null)
			{
				method = "inv-null";
				return 0;
			}
			try
			{
				_step = "Cap.CountItems.Invoke";
				_item = prefab + " shared=" + shared;
				MethodInfo method2 = inventory.GetType().GetMethod("CountItems", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3]
				{
					typeof(string),
					typeof(int),
					typeof(bool)
				}, null);
				if (method2 != null)
				{
					object value = method2.Invoke(inventory, new object[3] { shared, -1, true });
					method = "CountItems";
					return Convert.ToInt32(value);
				}
				method = "CountItems-missing";
			}
			catch (TargetInvocationException ex)
			{
				Fail("Cap.CountItems.Invoke", ex.InnerException ?? ex);
				method = "CountItems-threw";
			}
			catch (Exception ex2)
			{
				Fail("Cap.CountItems.Invoke", ex2);
				method = "CountItems-threw";
			}
			try
			{
				_step = "Cap.GetAllItems.Scan";
				int num = CountHaveByScan(inventory, shared);
				if (num >= 0)
				{
					method = "scan";
					return num;
				}
			}
			catch (Exception ex3)
			{
				Fail("Cap.GetAllItems.Scan", ex3);
				method = "scan-threw";
			}
			return 0;
		}

		private static int CountHaveByScan(object inventory, string shared)
		{
			MethodInfo method = inventory.GetType().GetMethod("GetAllItems", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (method == null)
			{
				return -1;
			}
			object obj = method.Invoke(inventory, null);
			if (obj == null)
			{
				return 0;
			}
			if (!(obj is IEnumerable enumerable))
			{
				return -1;
			}
			int num = 0;
			foreach (object item in enumerable)
			{
				if (item == null)
				{
					continue;
				}
				Type type = item.GetType();
				FieldInfo field = type.GetField("m_shared", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field2 = type.GetField("m_stack", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null || field2 == null)
				{
					continue;
				}
				object value = field.GetValue(item);
				if (value == null)
				{
					continue;
				}
				FieldInfo field3 = value.GetType().GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field3 == null))
				{
					string a = field3.GetValue(value) as string;
					if (string.Equals(a, shared, StringComparison.Ordinal))
					{
						num += Math.Max(0, Convert.ToInt32(field2.GetValue(item)));
					}
				}
			}
			return num;
		}

		private static string TryShared(ItemDrop drop, string prefab)
		{
			try
			{
				_step = "Read.m_itemData";
				_item = prefab;
				ItemData itemData = drop.m_itemData;
				if (itemData == null)
				{
					return string.Empty;
				}
				_step = "Read.m_shared";
				SharedData shared = itemData.m_shared;
				if (shared == null)
				{
					return string.Empty;
				}
				_step = "Read.m_shared.m_name";
				return shared.m_name ?? string.Empty;
			}
			catch (Exception ex)
			{
				Fail("TryShared", ex);
				return string.Empty;
			}
		}

		private static int TryStack(ItemDrop drop, string prefab)
		{
			try
			{
				_step = "Read.m_stack";
				_item = prefab;
				ItemData itemData = drop.m_itemData;
				return (itemData != null) ? Math.Max(1, itemData.m_stack) : (-1);
			}
			catch (Exception ex)
			{
				Fail("TryStack", ex);
				return -1;
			}
		}

		private static int TryMaxStack(ItemDrop drop, string prefab)
		{
			try
			{
				_step = "Read.m_maxStackSize";
				_item = prefab;
				ItemData itemData = drop.m_itemData;
				return (itemData?.m_shared != null) ? itemData.m_shared.m_maxStackSize : (-1);
			}
			catch (Exception ex)
			{
				Fail("TryMaxStack", ex);
				return -1;
			}
		}

		private static void Suppress(ItemDrop drop, string prefab)
		{
			try
			{
				_step = "Suppress.set_m_autoPickup_false";
				_item = prefab;
				drop.m_autoPickup = false;
				Suppressed.Add(drop);
			}
			catch (Exception ex)
			{
				Fail("Suppress", ex);
			}
		}

		[HarmonyPostfix]
		private static void Postfix(Player __instance, float dt)
		{
			_step = "Postfix";
			_item = "suppressed=" + Suppressed.Count;
			try
			{
				if (SonicPickupFiltersPlugin.DebugEnabled && Suppressed.Count > 0)
				{
					Log("Postfix restore count=" + Suppressed.Count);
				}
				RestoreSuppressed();
			}
			catch (Exception ex)
			{
				Fail("Postfix", ex);
				Suppressed.Clear();
			}
			PendingPickup.Clear();
			_step = "Postfix.done";
		}

		private static void RestoreSuppressed()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			for (int i = 0; i < Suppressed.Count; i++)
			{
				_step = "RestoreSuppressed[" + i + "]";
				ItemDrop val = Suppressed[i];
				if (!((Object)val == (Object)null))
				{
					try
					{
						_item = ((Object)((Component)val).gameObject).name;
					}
					catch
					{
						_item = "drop#" + i;
					}
					try
					{
						val.m_autoPickup = true;
					}
					catch (Exception ex)
					{
						Fail("RestoreSuppressed.set_true", ex);
					}
				}
			}
			Suppressed.Clear();
		}

		private static void Log(string message)
		{
			SonicPickupFiltersPlugin.DebugLog("#" + _passSeq + " [" + _step + "] " + message);
		}

		private static void Fail(string where, Exception ex)
		{
			_failLogs++;
			float unscaledTime = Time.unscaledTime;
			if (_failLogs <= 8 || !(unscaledTime < _nextFailLog))
			{
				_nextFailLog = unscaledTime + 2f;
				ManualLogSource modLogger = SonicPickupFiltersPlugin.ModLogger;
				if (modLogger != null)
				{
					modLogger.LogWarning((object)($"#{_passSeq} FAIL where={where} step={_step} item={_item} " + $"ex={ex.GetType().Name}: {ex.Message} (fail#{_failLogs})"));
				}
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Awake")]
	internal static class InventoryBarButton
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__TogglePanel;
		}

		private const string ButtonName = "sonic_pickupfilter_button";

		private const string IconItemPrefab = "Coins";

		private static readonly Vector3[] Corners = (Vector3[])(object)new Vector3[4];

		[HarmonyPostfix]
		private static void Postfix(InventoryGui __instance)
		{
			TryInject(__instance);
		}

		internal static void TryInjectExisting()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			InventoryGui instance = InventoryGui.instance;
			if ((Object)instance != (Object)null)
			{
				TryInject(instance);
			}
		}

		internal static void DestroyInjected()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			InventoryGui instance = InventoryGui.instance;
			if (!((Object)instance == (Object)null) && !((Object)instance.m_pvp == (Object)null))
			{
				Transform parent = ((Component)instance.m_pvp).transform.parent;
				Transform val = parent.Find("sonic_pickupfilter_button");
				if ((Object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
		}

		internal static void TryInject(InventoryGui __instance)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Expected O, but got Unknown
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Expected O, but got Unknown
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Invalid comparison between Unknown and I4
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Expected O, but got Unknown
			//IL_0198: Expected O, but got Unknown
			if (!SonicPickupFiltersPlugin.IsModEnabled() || GUIManagerMissing() || (Object)__instance == (Object)null)
			{
				return;
			}
			Toggle pvp = __instance.m_pvp;
			if ((Object)pvp == (Object)null)
			{
				SonicPickupFiltersPlugin.DebugLog("m_pvp missing; skip Pickup Filter inventory button.");
				return;
			}
			Transform parent = ((Component)pvp).transform.parent;
			Transform val = parent.Find("sonic_pickupfilter_button");
			if ((Object)val != (Object)null)
			{
				return;
			}
			Button val2 = FindTrophiesButton(parent, pvp);
			if ((Object)val2 == (Object)null)
			{
				SonicPickupFiltersPlugin.DebugLog("Trophies button not found; skip Pickup Filter inventory button.");
				return;
			}
			GameObject val3 = Object.Instantiate<GameObject>(((Component)val2).gameObject, parent);
			((Object)val3).name = "sonic_pickupfilter_button";
			Button component = val3.GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick = component.onClick;
			object obj = <>O.<0>__TogglePanel;
			if (obj == null)
			{
				UnityAction val4 = PickupFilterPanel.TogglePanel;
				<>O.<0>__TogglePanel = val4;
				obj = (object)val4;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			string text = ModLocalization.Translate("$sonic_pickupfilters_button", "Pickup Filter");
			TMP_Text componentInChildren = val3.GetComponentInChildren<TMP_Text>();
			if ((Object)componentInChildren != (Object)null)
			{
				componentInChildren.text = text;
			}
			else
			{
				Text componentInChildren2 = val3.GetComponentInChildren<Text>();
				if ((Object)componentInChildren2 != (Object)null)
				{
					componentInChildren2.text = text;
				}
			}
			UITooltip componentInChildren3 = val3.GetComponentInChildren<UITooltip>();
			if ((Object)componentInChildren3 != (Object)null)
			{
				componentInChildren3.m_topic = string.Empty;
				componentInChildren3.m_text = text;
			}
			Image val5 = FindIconImage(val3);
			if ((Object)val5 != (Object)null)
			{
				if ((int)((Selectable)component).transition == 2 && (Object)((Selectable)component).targetGraphic == (Object)val5)
				{
					((Selectable)component).transition = (Transition)1;
				}
				((MonoBehaviour)__instance).StartCoroutine(SwapIconWhenReady(val5));
			}
			LayoutRow(parent, ((Component)val2).GetComponent<RectTransform>(), val3.GetComponent<RectTransform>());
			SonicPickupFiltersPlugin.DebugLog("Pickup Filter inventory button injected.");
		}

		private static bool GUIManagerMissing()
		{
			try
			{
				return GUIManager.IsHeadless();
			}
			catch
			{
				return false;
			}
		}

		private static Button FindTrophiesButton(Transform bar, Toggle pvpToggle)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			Button result = null;
			float num = float.MaxValue;
			float num2 = WorldLeft(((Component)pvpToggle).GetComponent<RectTransform>());
			foreach (Transform item in bar)
			{
				Transform val = item;
				Button component = ((Component)val).GetComponent<Button>();
				if (!((Object)component == (Object)null))
				{
					if (((Object)val).name.IndexOf("Trophies", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return component;
					}
					float num3 = num2 - WorldRight((RectTransform)val);
					if (num3 > 0f && num3 < num)
					{
						num = num3;
						result = component;
					}
				}
			}
			return result;
		}

		private static Image FindIconImage(GameObject buttonGo)
		{
			//IL_0016: 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_0026: Expected O, but got Unknown
			//IL_0026: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			Image val = null;
			Image[] componentsInChildren = buttonGo.GetComponentsInChildren<Image>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)((Component)componentsInChildren[i]).gameObject != (Object)buttonGo)
				{
					val = componentsInChildren[i];
				}
			}
			if (!((Object)val != (Object)null))
			{
				return buttonGo.GetComponent<Image>();
			}
			return val;
		}

		private static IEnumerator SwapIconWhenReady(Image iconImage)
		{
			while ((Object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_items.Count == 0)
			{
				yield return null;
			}
			if ((Object)iconImage == (Object)null)
			{
				yield break;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Coins");
			Sprite val = null;
			if ((Object)itemPrefab != (Object)null)
			{
				ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
				if ((Object)component != (Object)null && component.m_itemData != null)
				{
					val = component.m_itemData.GetIcon();
				}
			}
			if ((Object)val != (Object)null)
			{
				iconImage.sprite = val;
			}
		}

		private static void LayoutRow(Transform bar, RectTransform trophiesRt, RectTransform insertedRt)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//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_0043: Expected O, but got Unknown
			//IL_0043: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Expected O, but got Unknown
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			List<RectTransform> list = new List<RectTransform>();
			foreach (Transform item in bar)
			{
				Transform val = item;
				if (((Component)val).gameObject.activeSelf && !((Object)val == (Object)((Component)insertedRt).transform) && !((Object)((Component)val).GetComponent<Selectable>() == (Object)null))
				{
					list.Add((RectTransform)val);
				}
			}
			if (list.Count != 0)
			{
				list.Sort((RectTransform a, RectTransform b) => WorldLeft(a).CompareTo(WorldLeft(b)));
				float num = bar.lossyScale.x;
				if (num <= 0f)
				{
					num = 1f;
				}
				List<float> list2 = new List<float>();
				for (int num2 = 1; num2 < list.Count; num2++)
				{
					list2.Add(WorldLeft(list[num2]) - WorldRight(list[num2 - 1]));
				}
				list2.Sort();
				float num3 = ((list2.Count > 0) ? list2[list2.Count / 2] : (8f * num));
				int num4 = list.IndexOf(trophiesRt);
				list.Insert((num4 >= 0) ? (num4 + 1) : list.Count, insertedRt);
				float num5 = 0f;
				for (int num6 = 0; num6 < list.Count; num6++)
				{
					num5 += WorldRight(list[num6]) - WorldLeft(list[num6]);
				}
				RectTransform rt = (RectTransform)bar;
				float num7 = WorldLeft(rt);
				float num8 = WorldRight(rt);
				float num9 = num8 - num7;
				float num10 = Mathf.Min(8f * num, Mathf.Max(0f, (num9 - num5) * 0.5f));
				float num11 = ((list.Count > 1) ? ((num9 - 2f * num10 - num5) / (float)(list.Count - 1)) : 0f);
				float num12 = Mathf.Max(0f, Mathf.Min(num3, num11));
				float num13 = num8 - num10;
				if (num9 < num5)
				{
					num13 = WorldRight(list[list.Count - 1]);
				}
				for (int num14 = list.Count - 1; num14 >= 0; num14--)
				{
					float num15 = WorldRight(list[num14]) - WorldLeft(list[num14]);
					float num16 = num13 - num15;
					Vector2 anchoredPosition = list[num14].anchoredPosition;
					anchoredPosition.x += (num16 - WorldLeft(list[num14])) / num;
					list[num14].anchoredPosition = anchoredPosition;
					num13 = num16 - num12;
				}
			}
		}

		private static float WorldLeft(RectTransform rt)
		{
			rt.GetWorldCorners(Corners);
			return Corners[0].x;
		}

		private static float WorldRight(RectTransform rt)
		{
			rt.GetWorldCorners(Corners);
			return Corners[2].x;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")]
	internal static class InventoryModifierClickPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(InventoryGrid grid, ItemData item, Vector2i pos)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_003a: 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_004f: Expected O, but got Unknown
			//IL_004f: Expected O, but got Unknown
			if (!SonicPickupFiltersPlugin.IsModEnabled())
			{
				return true;
			}
			if (!IsBlockToggleModifierHeld())
			{
				return true;
			}
			InventoryGui instance = InventoryGui.instance;
			if ((Object)instance == (Object)null || (Object)instance.m_playerGrid == (Object)null || (Object)grid != (Object)instance.m_playerGrid)
			{
				return true;
			}
			if (item == null || item.m_shared == null)
			{
				return true;
			}
			string text = ResolvePrefabName(item);
			if (string.IsNullOrEmpty(text))
			{
				return true;
			}
			if (PickupRuleStore.GetRule(text).Mode == PickupRuleMode.Block)
			{
				PickupRuleStore.SetRule(text, PickupRule.Allow);
				Message(FormatName(item) + ": auto-pickup allowed");
			}
			else
			{
				PickupRuleStore.SetRule(text, PickupRule.Block);
				Message(FormatName(item) + ": auto-pickup blocked");
			}
			PickupFilterPanel.RefreshIfOpen();
			return false;
		}

		internal unsafe static bool IsBlockToggleModifierHeld()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<KeyboardShortcut> inventoryBlockModifier = SonicPickupFiltersPlugin.InventoryBlockModifier;
			if (inventoryBlockModifier == null)
			{
				if (!Input.GetKey((KeyCode)308))
				{
					return Input.GetKey((KeyCode)307);
				}
				return true;
			}
			KeyboardShortcut value = inventoryBlockModifier.Value;
			object obj = KeyboardShortcut.Empty;
			if (((object)(*(KeyboardShortcut*)(&value))/*cast due to .constrained prefix*/).Equals(obj))
			{
				return false;
			}
			return ((KeyboardShortcut)(ref value)).IsPressed();
		}

		private static string FormatName(ItemData item)
		{
			if (Localization.instance == null || item.m_shared == null)
			{
				return item.m_shared?.m_name ?? "?";
			}
			return Localization.instance.Localize(item.m_shared.m_name);
		}

		private static string ResolvePrefabName(ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			if ((Object)item.m_dropPrefab != (Object)null)
			{
				return PickupRuleStore.NormalizePrefabName(((Object)item.m_dropPrefab).name);
			}
			if ((Object)ObjectDB.instance == (Object)null || item.m_shared == null)
			{
				return string.Empty;
			}
			foreach (GameObject item2 in ObjectDB.instance.m_items)
			{
				if (!((Object)item2 == (Object)null))
				{
					ItemDrop component = item2.GetComponent<ItemDrop>();
					if (!((Object)component == (Object)null) && component.m_itemData?.m_shared != null && component.m_itemData.m_shared.m_name == item.m_shared.m_name)
					{
						return PickupRuleStore.NormalizePrefabName(((Object)item2).name);
					}
				}
			}
			return string.Empty;
		}

		private static void Message(string text)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			Player localPlayer = Player.m_localPlayer;
			if ((Object)localPlayer != (Object)null)
			{
				((Character)localPlayer).Message((MessageType)1, text, 0, (Sprite)null, false);
			}
		}
	}
	internal static class ItemMatch
	{
		internal static bool MatchesSearch(ItemDrop drop, string pattern)
		{
			if ((Object)(object)drop == (Object)null)
			{
				return false;
			}
			if (string.IsNullOrWhiteSpace(pattern))
			{
				return true;
			}
			string value = PickupRuleStore.NormalizePrefabName(((Object)drop).name);
			string text = drop.m_itemData?.m_shared?.m_name ?? string.Empty;
			string localized = GetLocalized(text);
			if (!LocateNameMatches(value, pattern) && !LocateNameMatches(text, pattern) && !LocateNameMatches(localized, pattern))
			{
				if (text.StartsWith("$", StringComparison.Ordinal))
				{
					return LocateNameMatches(text.Substring(1), pattern);
				}
				return false;
			}
			return true;
		}

		internal static string GetLocalized(string sharedName)
		{
			if (string.IsNullOrEmpty(sharedName))
			{
				return string.Empty;
			}
			if (Localization.instance != null)
			{
				return Localization.instance.Localize(sharedName);
			}
			return sharedName;
		}

		internal unsafe static string FriendlyItemTypeLabel(ItemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected I4, but got Unknown
			return (int)type switch
			{
				0 => "None", 
				1 => "Materials", 
				2 => "Food & Mead", 
				3 => "One-handed weapons", 
				14 => "Two-handed weapons", 
				22 => "Two-handed (left)", 
				4 => "Bows", 
				5 => "Shields", 
				6 => "Helmets", 
				7 => "Chest armor", 
				11 => "Leg armor", 
				12 => "Hands", 
				17 => "Capes & shoulders", 
				9 => "Ammo", 
				23 => "Thrown / ammo", 
				19 => "Tools", 
				18 => "Utility", 
				15 => "Torches", 
				13 => "Trophies", 
				16 => "Misc", 
				10 => "Customization", 
				20 => "Atgeir attach", 
				21 => "Fish", 
				24 => "Trinkets", 
				_ => SpaceEnumName(((object)(*(ItemType*)(&type))/*cast due to .constrained prefix*/).ToString()), 
			};
		}

		private static string SpaceEnumName(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return value;
			}
			StringBuilder stringBuilder = new StringBuilder(value.Length + 8);
			for (int i = 0; i < value.Length; i++)
			{
				char c = value[i];
				if (i > 0 && char.IsUpper(c) && !char.IsUpper(value[i - 1]))
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(c);
			}
			return stringBuilder.ToString();
		}

		private static bool LocateNameMatches(string value, string pattern)
		{
			if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(pattern))
			{
				return false;
			}
			if (NameMatches(value, pattern))
			{
				return true;
			}
			string text = pattern.Replace("*", string.Empty).Trim();
			if (text.Length == 0)
			{
				return false;
			}
			return value.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static bool NameMatches(string value, string pattern)
		{
			if (string.IsNullOrEmpty(pattern))
			{
				return false;
			}
			if (pattern.IndexOf('*') < 0)
			{
				return string.Equals(value, pattern, StringComparison.OrdinalIgnoreCase);
			}
			string[] array = pattern.Split('*');
			int num = 0;
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i];
				if (text.Length == 0)
				{
					continue;
				}
				if (i == 0)
				{
					if (!value.StartsWith(text, StringComparison.OrdinalIgnoreCase))
					{
						return false;
					}
					num = text.Length;
					continue;
				}
				if (i == array.Length - 1 && pattern[pattern.Length - 1] != '*')
				{
					if (!value.EndsWith(text, StringComparison.OrdinalIgnoreCase))
					{
						return false;
					}
					return value.Length - text.Length >= num;
				}
				int num2 = value.IndexOf(text, num, StringComparison.OrdinalIgnoreCase);
				if (num2 < 0)
				{
					return false;
				}
				num = num2 + text.Length;
			}
			return true;
		}
	}
	internal static class ModLocalization
	{
		internal const string Title = "$sonic_pickupfilters_title";

		internal const string Hint = "$sonic_pickupfilters_hint";

		internal const string SearchPlaceholder = "$sonic_pickupfilters_search";

		internal const string CategoryAll = "$sonic_pickupfilters_cat_all";

		internal const string Clear = "$sonic_pickupfilters_clear";

		internal const string TabAll = "$sonic_pickupfilters_tab_all";

		internal const string TabBlocked = "$sonic_pickupfilters_tab_blocked";

		internal const string TabCapped = "$sonic_pickupfilters_tab_capped";

		internal const string Close = "$sonic_pickupfilters_close";

		internal const string Button = "$sonic_pickupfilters_button";

		internal const string ColItem = "$sonic_pickupfilters_col_item";

		internal const string ColBlock = "$sonic_pickupfilters_col_block";

		internal const string ColCap = "$sonic_pickupfilters_col_cap";

		internal const string TipBlockTopic = "$sonic_pickupfilters_tip_block_topic";

		internal const string TipBlockBody = "$sonic_pickupfilters_tip_block_body";

		internal const string TipCapTopic = "$sonic_pickupfilters_tip_cap_topic";

		internal const string TipCapBody = "$sonic_pickupfilters_tip_cap_body";

		internal const string TipItemTopic = "$sonic_pickupfilters_tip_item_topic";

		internal const string TipItemBody = "$sonic_pickupfilters_tip_item_body";

		internal const string CapPlaceholderOff = "$sonic_pickupfilters_cap_ph_off";

		internal const string CapPlaceholderOn = "$sonic_pickupfilters_cap_ph_on";

		private static CustomLocalization _localization;

		internal static void Register()
		{
			if (LocalizationManager.Instance != null)
			{
				_localization = LocalizationManager.Instance.GetLocalization();
				CustomLocalization localization = _localization;
				string text = "English";
				localization.AddTranslation(ref text, new Dictionary<string, string>
				{
					{ "sonic_pickupfilters_title", "Pickup Filter" },
					{ "sonic_pickupfilters_hint", "Check Block to turn filtering on. Cap is optional — leave empty to never auto-pick, or type a max count. Cap alone (Block off) does nothing." },
					{ "sonic_pickupfilters_search", "Search items…" },
					{ "sonic_pickupfilters_cat_all", "All categories" },
					{ "sonic_pickupfilters_clear", "Clear" },
					{ "sonic_pickupfilters_tab_all", "All" },
					{ "sonic_pickupfilters_tab_blocked", "Blocked" },
					{ "sonic_pickupfilters_tab_capped", "Capped" },
					{ "sonic_pickupfilters_close", "Close" },
					{ "sonic_pickupfilters_button", "Pickup Filter" },
					{ "sonic_pickupfilters_col_item", "Item" },
					{ "sonic_pickupfilters_col_block", "Block" },
					{ "sonic_pickupfilters_col_cap", "Cap" },
					{ "sonic_pickupfilters_tip_block_topic", "Block" },
					{ "sonic_pickupfilters_tip_block_body", "Turns filtering on for this item.\nOff = vanilla auto-pickup (Cap ignored).\nOn + empty Cap = never auto-pick.\nOn + Cap number = auto-pick until that count." },
					{ "sonic_pickupfilters_tip_cap_topic", "Cap" },
					{ "sonic_pickupfilters_tip_cap_body", "Only works while Block is checked.\nEmpty Cap = full block (never auto-pick).\nNumber = keep auto-picking until you hold that many.\nCap with Block unchecked does nothing." },
					{ "sonic_pickupfilters_tip_item_topic", "Item" },
					{ "sonic_pickupfilters_tip_item_body", "Discovered items from your world. Use Block + Cap to control auto-pickup. Manual Use still works when blocked." },
					{ "sonic_pickupfilters_cap_ph_off", "need Block" },
					{ "sonic_pickupfilters_cap_ph_on", "∞ block" }
				});
			}
		}

		internal static string Translate(string token, string fallback)
		{
			if (_localization != null)
			{
				string text = _localization.TryTranslate(token);
				if (!string.IsNullOrEmpty(text) && text[0] != '[' && text != token)
				{
					return text;
				}
			}
			if (LocalizationManager.Instance != null)
			{
				string text2 = LocalizationManager.Instance.TryTranslate(token);
				if (!string.IsNullOrEmpty(text2) && text2[0] != '[' && text2 != token)
				{
					return text2;
				}
			}
			return fallback;
		}
	}
	internal static class PickupFilterPanel
	{
		private enum ViewTab
		{
			All,
			Blocked,
			Capped
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction<string> <0>__OnSearchChanged;

			public static UnityAction <1>__ClearFilters;

			public static UnityAction<int> <2>__OnCategoryChanged;

			public static Func<ItemDrop, ItemType> <3>__GetItemType;

			public static UnityAction <4>__ApplyCapEditor;

			public static UnityAction <5>__HideCapEditor;
		}

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

			public static UnityAction <>9__55_0;

			public static UnityAction <>9__55_1;

			public static UnityAction <>9__55_2;

			public static UnityAction <>9__55_3;

			public static Func<ItemType, string> <>9__67_0;

			public static Func<ItemType, ItemType?> <>9__67_1;

			public static Func<ItemDrop, bool> <>9__71_0;

			public static Func<ItemDrop, bool> <>9__71_1;

			public static Func<ItemDrop, bool> <>9__71_2;

			public static Func<IGrouping<ItemType, ItemDrop>, string> <>9__71_3;

			public static Func<ItemDrop, string> <>9__71_6;

			public static Func<IGrouping<ItemType, ItemDrop>, int> <>9__71_4;

			public static Func<ItemDrop, string> <>9__71_7;

			public static Func<IGrouping<string, ItemDrop>, ItemDrop> <>9__71_8;

			public static Func<ItemDrop, string> <>9__71_9;

			public static Func<ItemDrop, string> <>9__73_0;

			public static UnityAction <>9__93_0;

			public static UnityAction <>9__93_1;

			public static UnityAction <>9__93_2;

			public static UnityAction <>9__93_3;

			internal void <BuildPanel>b__55_0()
			{
				SetViewTab(ViewTab.All);
			}

			internal void <BuildPanel>b__55_1()
			{
				SetViewTab(ViewTab.Blocked);
			}

			internal void <BuildPanel>b__55_2()
			{
				SetViewTab(ViewTab.Capped);
			}

			internal void <BuildPanel>b__55_3()
			{
				if (IsOpen)
				{
					TogglePanel();
				}
			}

			internal string <EnsureCategoryOptions>b__67_0(ItemType t)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				return ItemMatch.FriendlyItemTypeLabel(t);
			}

			internal ItemType? <EnsureCategoryOptions>b__67_1(ItemType t)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				return t;
			}

			internal bool <RefreshContent>b__71_0(ItemDrop d)
			{
				return ItemMatch.MatchesSearch(d, _searchText);
			}

			internal bool <RefreshContent>b__71_1(ItemDrop d)
			{
				return PickupRuleStore.GetRule(PickupRuleStore.NormalizePrefabName(((Object)d).name)).Mode == PickupRuleMode.Block;
			}

			internal bool <RefreshContent>b__71_2(ItemDrop d)
			{
				return PickupRuleStore.GetRule(PickupRuleStore.NormalizePrefabName(((Object)d).name)).Mode == PickupRuleMode.Cap;
			}

			internal string <RefreshContent>b__71_3(IGrouping<ItemType, ItemDrop> g)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return ItemMatch.FriendlyItemTypeLabel(g.Key);
			}

			internal int <RefreshContent>b__71_4(IGrouping<ItemType, ItemDrop> g)
			{
				return g.Select((ItemDrop d) => PickupRuleStore.NormalizePrefabName(((Object)d).name)).Distinct<string>(StringComparer.OrdinalIgnoreCase).Count();
			}

			internal string <RefreshContent>b__71_6(ItemDrop d)
			{
				return PickupRuleStore.NormalizePrefabName(((Object)d).name);
			}

			internal string <RefreshContent>b__71_7(ItemDrop d)
			{
				return PickupRuleStore.NormalizePrefabName(((Object)d).name);
			}

			internal ItemDrop <RefreshContent>b__71_8(IGrouping<string, ItemDrop> g)
			{
				return g.First();
			}

			internal string <RefreshContent>b__71_9(ItemDrop d)
			{
				return ItemMatch.GetLocalized(d.m_itemData?.m_shared?.m_name);
			}

			internal string <EstimateContentHeight>b__73_0(ItemDrop d)
			{
				return PickupRuleStore.NormalizePrefabName(((Object)d).name);
			}

			internal void <EnsureCapEditor>b__93_0()
			{
				NudgeCap(-1);
			}

			internal void <EnsureCapEditor>b__93_1()
			{
				NudgeCap(1);
			}

			internal void <EnsureCapEditor>b__93_2()
			{
				NudgeCap(-_capEditDefault);
			}

			internal void <EnsureCapEditor>b__93_3()
			{
				NudgeCap(_capEditDefault);
			}
		}

		private const float PanelW = 980f;

		private const float PanelH = 780f;

		private const float RowHeight = 36f;

		private const float ItemRowHeight = 36f;

		private const float CategoryHeaderHeight = 22f;

		private const float ScrollH = 500f;

		private const float RowInnerW = 880f;

		private const float IconSize = 28f;

		private const float ToggleSize = 28f;

		private const float CapFieldW = 90f;

		private const float CapFieldH = 28f;

		private const float ColIconX = 8f;

		private const float ColNameX = 44f;

		private const float ColNameW = 540f;

		private const float ColBlockX = 620f;

		private const float ColCapX = 720f;

		private static readonly FieldInfo KnownMaterialField = AccessTools.Field(typeof(Player), "m_knownMaterial");

		private static readonly Dictionary<string, Sprite> IconCache = new Dictionary<string, Sprite>();

		private static readonly Color ColNormal = Color.white;

		private static readonly Color ColBlocked = new Color(1f, 0.25f, 0.25f, 1f);

		private static readonly Color ColCapped = new Color(1f, 0.85f, 0.35f, 1f);

		private static GameObject _panel;

		private static RectTransform _contentRoot;

		private static ScrollRect _scrollRect;

		private static InputField _searchInput;

		private static Dropdown _categoryDropdown;

		private static Text _tabAllLabel;

		private static Text _tabBlockedLabel;

		private static Text _tabCappedLabel;

		private static Button _tabAllButton;

		private static Button _tabBlockedButton;

		private static Button _tabCappedButton;

		private static GameObject _capEditor;

		private static InputField _capInput;

		private static Text _capEditorTitle;

		private static string _capEditPrefab = string.Empty;

		private static int _capEditDefault = 1;

		private static bool _guiReady;

		private static string _searchText = string.Empty;

		private static int _categoryIndex;

		private static ViewTab _viewTab = ViewTab.All;

		private static List<ItemType?> _categoryOptions = new List<ItemType?> { null };

		private static List<string> _categoryLabels = new List<string>();

		private static bool _suppressCategoryCallback;

		private static bool _refreshQueued;

		private static int _refreshReadyFrame;

		private static float _contentWidth = 900f;

		private static UITooltip _tooltipTemplate;

		internal static bool IsOpen
		{
			get
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Expected O, but got Unknown
				if ((Object)_panel != (Object)null)
				{
					return _panel.activeSelf;
				}
				return false;
			}
		}

		internal static void OnGuiReady()
		{
			_guiReady = GUIManager.Instance != null && (Object)(object)GUIManager.CustomGUIFront != (Object)null;
		}

		internal static void TogglePanel()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			if (!_guiReady && GUIManager.Instance != null)
			{
				_guiReady = (Object)(object)GUIManager.CustomGUIFront != (Object)null;
			}
			if (!_guiReady || GUIManager.IsHeadless())
			{
				return;
			}
			if ((Object)_panel == (Object)null)
			{
				BuildPanel();
			}
			else if ((Object)_contentRoot == (Object)null || (Object)_scrollRect == (Object)null)
			{
				DestroyPanel();
				BuildPanel();
			}
			if (!((Object)_panel == (Object)null))
			{
				bool flag = !_panel.activeSelf;
				_panel.SetActive(flag);
				GUIManager.BlockInput(flag);
				SonicPickupFiltersPlugin.DebugLog("TogglePanel open=" + flag);
				if (flag)
				{
					_viewTab = ViewTab.All;
					EnsureCategoryOptions();
					RefreshContent();
				}
				else
				{
					_refreshQueued = false;
					HideCapEditor();
				}
			}
		}

		internal static void RefreshIfOpen()
		{
			if (IsOpen)
			{
				RefreshContent();
			}
		}

		internal static void ProcessQueuedRefresh()
		{
			if (_refreshQueued && Time.frameCount >= _refreshReadyFrame)
			{
				_refreshQueued = false;
				if (IsOpen)
				{
					RefreshContent();
				}
			}
		}

		internal static void DestroyPanel()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			if ((Object)_panel != (Object)null)
			{
				Object.Destroy((Object)(object)_panel);
			}
			_panel = null;
			_contentRoot = null;
			_scrollRect = null;
			_searchInput = null;
			_categoryDropdown = null;
			_tabAllLabel = null;
			_tabBlockedLabel = null;
			_tabCappedLabel = null;
			_tabAllButton = null;
			_tabBlockedButton = null;
			_tabCappedButton = null;
			_capEditor = null;
			_capInput = null;
			_capEditorTitle = null;
			_capEditPrefab = string.Empty;
			_viewTab = ViewTab.All;
			_searchText = string.Empty;
			_categoryIndex = 0;
			_categoryLabels.Clear();
			_suppressCategoryCallback = false;
			_refreshQueued = false;
			_refreshReadyFrame = 0;
			_tooltipTemplate = null;
		}

		private static void BuildPanel()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0047: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: 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_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Expected O, but got Unknown
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Expected O, but got Unknown
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Expected O, but got Unknown
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Expected O, but got Unknown
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Expected O, but got Unknown
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_042c: Unknown result type (might be due to invalid IL or missing references)
			//IL_043b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0440: Unknown result type (might be due to invalid IL or missing references)
			//IL_047a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Expected O, but got Unknown
			//IL_040c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Expected O, but got Unknown
			//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0521: Unknown result type (might be due to invalid IL or missing references)
			//IL_0537: Unknown result type (might be due to invalid IL or missing references)
			//IL_054d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0563: Unknown result type (might be due to invalid IL or missing references)
			//IL_05aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b5: Expected O, but got Unknown
			//IL_0620: Unknown result type (might be due to invalid IL or missing references)
			//IL_062b: Expected O, but got Unknown
			//IL_06ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_06dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0734: Unknown result type (might be due to invalid IL or missing references)
			//IL_0739: Unknown result type (might be due to invalid IL or missing references)
			//IL_073f: Expected O, but got Unknown
			//IL_066c: Unknown result type (might be due to invalid IL or missing references)
			if (GUIManager.Instance == null || (Object)GUIManager.CustomGUIFront == (Object)null)
			{
				ManualLogSource modLogger = SonicPickupFiltersPlugin.ModLogger;
				if (modLogger != null)
				{
					modLogger.LogError((object)"GUIManager not ready for Pickup Filter panel.");
				}
				return;
			}
			_panel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 980f, 780f, true);
			_panel.SetActive(false);
			GUIManager.Instance.CreateText(ModLocalization.Translate("$sonic_pickupfilters_title", "Pickup Filter"), _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -36f), GUIManager.Instance.AveriaSerifBold, 28, GUIManager.Instance.ValheimOrange, true, Color.black, 500f, 36f, false);
			GameObject val = GUIManager.Instance.CreateText(ModLocalization.Translate("$sonic_pickupfilters_hint", "Check Block to turn filtering on. Cap is optional — leave empty to never auto-pick, or type a max count. Cap alone (Block off) does nothing."), _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -78f), GUIManager.Instance.AveriaSerifBold, 12, Color.white, true, Color.black, 900f, 40f, false);
			Text component = val.GetComponent<Text>();
			if ((Object)component != (Object)null)
			{
				component.alignment = (TextAnchor)1;
				component.horizontalOverflow = (HorizontalWrapMode)0;
				component.verticalOverflow = (VerticalWrapMode)1;
			}
			RectTransform row = CreateRow("TabRow", new Vector2(0f, -128f), 920f, 36f);
			object obj = <>c.<>9__55_0;
			if (obj == null)
			{
				UnityAction val2 = delegate
				{
					SetViewTab(ViewTab.All);
				};
				<>c.<>9__55_0 = val2;
				obj = (object)val2;
			}
			_tabAllButton = AddRowButton(row, "All", 140f, (UnityAction)obj, out _tabAllLabel);
			object obj2 = <>c.<>9__55_1;
			if (obj2 == null)
			{
				UnityAction val3 = delegate
				{
					SetViewTab(ViewTab.Blocked);
				};
				<>c.<>9__55_1 = val3;
				obj2 = (object)val3;
			}
			_tabBlockedButton = AddRowButton(row, "Blocked", 160f, (UnityAction)obj2, out _tabBlockedLabel);
			object obj3 = <>c.<>9__55_2;
			if (obj3 == null)
			{
				UnityAction val4 = delegate
				{
					SetViewTab(ViewTab.Capped);
				};
				<>c.<>9__55_2 = val4;
				obj3 = (object)val4;
			}
			_tabCappedButton = AddRowButton(row, "Capped", 160f, (UnityAction)obj3, out _tabCappedLabel);
			AttachTooltip(((Component)_tabBlockedButton).gameObject, ModLocalization.Translate("$sonic_pickupfilters_tab_blocked", "Blocked"), "Items with Block on and no Cap (never auto-picked).");
			AttachTooltip(((Component)_tabCappedButton).gameObject, ModLocalization.Translate("$sonic_pickupfilters_tab_capped", "Capped"), "Items with Block on and a Cap number (auto-pick until that count).");
			RectTransform val5 = CreateRow("FilterRow", new Vector2(0f, -176f), 920f, 36f);
			GameObject val6 = GUIManager.Instance.CreateInputField((Transform)(object)val5, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, (ContentType)0, ModLocalization.Translate("$sonic_pickupfilters_search", "Search items…"), 14, 360f, 36f);
			PrepareLayoutChild(val6, 360f, 36f);
			_searchInput = val6.GetComponent<InputField>();
			if ((Object)_searchInput != (Object)null)
			{
				GUIManager.Instance.ApplyInputFieldStyle(_searchInput, 14);
				((UnityEvent<string>)(object)_searchInput.onValueChanged).AddListener((UnityAction<string>)OnSearchChanged);
			}
			GameObject val7 = GUIManager.Instance.CreateButton(ModLocalization.Translate("$sonic_pickupfilters_clear", "Clear"), (Transform)(object)val5, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 100f, 36f);
			PrepareLayoutChild(val7, 100f, 36f);
			Button component2 = val7.GetComponent<Button>();
			GUIManager.Instance.ApplyButtonStyle(component2, 14);
			ButtonClickedEvent onClick = component2.onClick;
			object obj4 = <>O.<1>__ClearFilters;
			if (obj4 == null)
			{
				UnityAction val8 = ClearFilters;
				<>O.<1>__ClearFilters = val8;
				obj4 = (object)val8;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj4);
			GameObject val9 = GUIManager.Instance.CreateDropDown((Transform)(object)val5, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 14, 280f, 36f);
			PrepareLayoutChild(val9, 280f, 36f);
			_categoryDropdown = val9.GetComponent<Dropdown>();
			if ((Object)_categoryDropdown != (Object)null)
			{
				FixDropdownOptionHits(_categoryDropdown, 26f);
				((UnityEvent<int>)(object)_categoryDropdown.onValueChanged).AddListener((UnityAction<int>)OnCategoryChanged);
			}
			GameObject val10 = GUIManager.Instance.CreateScrollView(_panel.transform, false, true, 8f, 2f, GUIManager.Instance.ValheimScrollbarHandleColorBlock, GUIManager.Instance.ValheimBeige, 920f, 500f);
			((Object)val10).name = "PickupFilterScroll";
			RectTransform component3 = val10.GetComponent<RectTransform>();
			component3.anchorMin = new Vector2(0.5f, 1f);
			component3.anchorMax = new Vector2(0.5f, 1f);
			component3.pivot = new Vector2(0.5f, 1f);
			component3.anchoredPosition = new Vector2(0f, -228f);
			component3.SetSizeWithCurrentAnchors((Axis)0, 920f);
			component3.SetSizeWithCurrentAnchors((Axis)1, 500f);
			FixJotunnScrollFill(val10, 920f, 500f);
			_scrollRect = val10.GetComponentInChildren<ScrollRect>(true);
			if ((Object)_scrollRect == (Object)null)
			{
				ManualLogSource modLogger2 = SonicPickupFiltersPlugin.ModLogger;
				if (modLogger2 != null)
				{
					modLogger2.LogError((object)"ScrollRect missing.");
				}
				return;
			}
			_scrollRect.horizontal = false;
			_scrollRect.vertical = true;
			_scrollRect.movementType = (MovementType)2;
			_scrollRect.scrollSensitivity = 120f;
			_scrollRect.verticalScrollbarVisibility = (ScrollbarVisibility)1;
			GUIManager.Instance.ApplyScrollRectStyle(_scrollRect);
			if ((Object)_scrollRect.viewport != (Object)null)
			{
				Image val11 = ((Component)_scrollRect.viewport).GetComponent<Image>() ?? ((Component)_scrollRect.viewport).gameObject.AddComponent<Image>();
				((Graphic)val11).color = new Color(0f, 0f, 0f, 0.01f);
				((Graphic)val11).raycastTarget = true;
			}
			_contentRoot = _scrollRect.content;
			_contentWidth = 908f;
			ConfigureContentRoot(_contentRoot, _contentWidth);
			GameObject val12 = GUIManager.Instance.CreateButton(ModLocalization.Translate("$sonic_pickupfilters_close", "Close"), _panel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 40f), 200f, 48f);
			Button component4 = val12.GetComponent<Button>();
			GUIManager.Instance.ApplyButtonStyle(component4, 16);
			ButtonClickedEvent onClick2 = component4.onClick;
			object obj5 = <>c.<>9__55_3;
			if (obj5 == null)
			{
				UnityAction val13 = delegate
				{
					if (IsOpen)
					{
						TogglePanel();
					}
				};
				<>c.<>9__55_3 = val13;
				obj5 = (object)val13;
			}
			((UnityEvent)onClick2).AddListener((UnityAction)obj5);
		}

		private static RectTransform CreateRow(string name, Vector2 anchoredPos, float width, float height)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_004f: 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_0079: 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_008d: 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_00b8: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(HorizontalLayoutGroup)
			});
			val.transform.SetParent(_panel.transform, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.5f, 1f);
			component.anchorMax = new Vector2(0.5f, 1f);
			component.pivot = new Vector2(0.5f, 1f);
			component.anchoredPosition = anchoredPos;
			component.sizeDelta = new Vector2(width, height);
			HorizontalLayoutGroup component2 = val.GetComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component2).spacing = 10f;
			((LayoutGroup)component2).padding = new RectOffset(0, 0, 0, 0);
			((LayoutGroup)component2).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)component2).childControlWidth = false;
			((HorizontalOrVerticalLayoutGroup)component2).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false;
			return component;
		}

		private static Button AddRowButton(RectTransform row, string label, float width, UnityAction onClick, out Text labelText)
		{
			//IL_0011: 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)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GUIManager.Instance.CreateButton(label, (Transform)(object)row, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, width, 36f);
			PrepareLayoutChild(val, width, 36f);
			Button component = val.GetComponent<Button>();
			GUIManager.Instance.ApplyButtonStyle(component, 14);
			((UnityEvent)component.onClick).AddListener(onClick);
			labelText = val.GetComponentInChildren<Text>();
			return component;
		}

		private static void PrepareLayoutChild(GameObject go, float width, float height)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			if ((Object)component != (Object)null)
			{
				component.anchorMin = new Vector2(0.5f, 0.5f);
				component.anchorMax = new Vector2(0.5f, 0.5f);
				component.pivot = new Vector2(0.5f, 0.5f);
				component.sizeDelta = new Vector2(width, height);
				component.anchoredPosition = Vector2.zero;
				((Transform)component).localScale = Vector3.one;
			}
			LayoutElement val = go.GetComponent<LayoutElement>() ?? go.AddComponent<LayoutElement>();
			val.preferredWidth = width;
			val.preferredHeight = height;
			val.minWidth = width;
			val.minHeight = height;
			val.flexibleWidth = 0f;
			val.flexibleHeight = 0f;
		}

		private static void FixJotunnScrollFill(GameObject scrollRoot, float width, float height)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			Transform val = scrollRoot.transform.Find("Scroll View");
			if (!((Object)val == (Object)null))
			{
				RectTransform component = ((Component)val).GetComponent<RectTransform>();
				component.anchorMin = Vector2.zero;
				component.anchorMax = Vector2.one;
				component.pivot = new Vector2(0.5f, 0.5f);
				component.offsetMin = Vector2.zero;
				component.offsetMax = Vector2.zero;
				component.anchoredPosition = Vector2.zero;
				((Transform)component).localScale = Vector3.one;
				Transform val2 = val.Find("Viewport");
				if ((Object)val2 != (Object)null)
				{
					RectTransform component2 = ((Component)val2).GetComponent<RectTransform>();
					component2.anchorMin = Vector2.zero;
					component2.anchorMax = Vector2.one;
					component2.pivot = new Vector2(0.5f, 0.5f);
					component2.offsetMin = new Vector2(0f, 0f);
					component2.offsetMax = new Vector2(-10f, 0f);
					component2.anchoredPosition = Vector2.zero;
				}
			}
		}

		private static void ConfigureContentRoot(RectTransform content, float width)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			VerticalLayoutGroup val = ((Component)content).GetComponent<VerticalLayoutGroup>() ?? ((Component)content).gameObject.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)val).childAlignment = (TextAnchor)0;
			((HorizontalOrVerticalLayoutGroup)val).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)val).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)val).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)val).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)val).spacing = 4f;
			((LayoutGroup)val).padding = new RectOffset(8, 8, 8, 8);
			ContentSizeFitter val2 = ((Component)content).GetComponent<ContentSizeFitter>() ?? ((Component)content).gameObject.AddComponent<ContentSizeFitter>();
			val2.horizontalFit = (FitMode)0;
			val2.verticalFit = (FitMode)2;
			content.anchorMin = new Vector2(0f, 1f);
			content.anchorMax = new Vector2(0f, 1f);
			content.pivot = new Vector2(0f, 1f);
			content.anchoredPosition = Vector2.zero;
			content.SetSizeWithCurrentAnchors((Axis)0, width);
			((Transform)content).localScale = Vector3.one;
			GraphicRaycaster component = ((Component)content).GetComponent<GraphicRaycaster>();
			if ((Object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			Canvas component2 = ((Component)content).GetComponent<Canvas>();
			if ((Object)component2 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component2);
			}
		}

		private static void OnSearchChanged(string value)
		{
			_searchText = value ?? string.Empty;
			SonicPickupFiltersPlugin.DebugLog("Search='" + _searchText + "'");
			RefreshContent();
		}

		private static void OnCategoryChanged(int index)
		{
			if (!_suppressCategoryCallback)
			{
				_categoryIndex = index;
				string text = ((index >= 0 && index < _categoryLabels.Count) ? _categoryLabels[index] : "?");
				SonicPickupFiltersPlugin.DebugLog("Category dropdown → " + index + " (" + text + ")");
				_refreshReadyFrame = Time.frameCount + 2;
				_refreshQueued = true;
			}
		}

		private static void ClearFilters()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			_searchText = string.Empty;
			_categoryIndex = 0;
			if ((Object)_searchInput != (Object)null)
			{
				_searchInput.SetTextWithoutNotify(string.Empty);
			}
			SetCategoryDropdownValue(0);
			RefreshContent();
		}

		private static void SetViewTab(ViewTab tab)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			_viewTab = tab;
			_categoryIndex = 0;
			SetCategoryDropdownValue(0);
			if ((Object)_searchInput != (Object)null && !string.IsNullOrEmpty(_searchText))
			{
				SonicPickupFiltersPlugin.DebugLog("Tab " + tab.ToString() + " with search still='" + _searchText + "'");
			}
			RefreshContent();
		}

		private static void UpdateTabLabels()
		{
			SetTabLabel(_tabAllLabel, _tabAllButton, ViewTab.All, ModLocalization.Translate("$sonic_pickupfilters_tab_all", "All"));
			SetTabLabel(_tabBlockedLabel, _tabBlockedButton, ViewTab.Blocked, ModLocalization.Translate("$sonic_pickupfilters_tab_blocked", "Blocked") + " (" + PickupRuleStore.CountByMode(PickupRuleMode.Block) + ")");
			SetTabLabel(_tabCappedLabel, _tabCappedButton, ViewTab.Capped, ModLocalization.Translate("$sonic_pickupfilters_tab_capped", "Capped") + " (" + PickupRuleStore.CountByMode(PickupRuleMode.Cap) + ")");
		}

		private static void SetTabLabel(Text label, Button button, ViewTab tab, string text)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0043: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)label != (Object)null)
			{
				label.text = text;
				((Graphic)label).color = ((_viewTab == tab) ? GUIManager.Instance.ValheimOrange : Color.white);
			}
			if ((Object)button != (Object)null)
			{
				ColorBlock colors = ((Selectable)button).colors;
				((ColorBlock)(ref colors)).normalColor = (Color)((_viewTab == tab) ? new Color(1f, 0.85f, 0.55f, 1f) : Color.white);
				((Selectable)button).colors = colors;
			}
		}

		private static void EnsureCategoryOptions()
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			List<ItemType> list = (from t in GetKnownItems().Select(GetItemType).Distinct()
				orderby ItemMatch.FriendlyItemTypeLabel(t)
				select t).ToList();
			_categoryOptions = new List<ItemType?> { null };
			_categoryOptions.AddRange(((IEnumerable<ItemType>)list).Select((Func<ItemType, ItemType?>)((ItemType t) => t)));
			List<string> list2 = new List<string> { ModLocalization.Translate("$sonic_pickupfilters_cat_all", "All categories") };
			for (int num = 0; num < list.Count; num++)
			{
				list2.Add(ItemMatch.FriendlyItemTypeLabel(list[num]));
			}
			if (_categoryIndex < 0 || _categoryIndex >= _categoryOptions.Count)
			{
				_categoryIndex = 0;
			}
			bool flag = list2.Count == _categoryLabels.Count;
			if (flag)
			{
				for (int num2 = 0; num2 < list2.Count; num2++)
				{
					if (!string.Equals(list2[num2], _categoryLabels[num2], StringComparison.Ordinal))
					{
						flag = false;
						break;
					}
				}
			}
			if (flag)
			{
				SetCategoryDropdownValue(_categoryIndex);
				return;
			}
			_categoryLabels = list2;
			if (!((Object)_categoryDropdown == (Object)null))
			{
				_suppressCategoryCallback = true;
				try
				{
					_categoryDropdown.ClearOptions();
					_categoryDropdown.AddOptions(list2);
					_categoryDropdown.SetValueWithoutNotify(_categoryIndex);
				}
				finally
				{
					_suppressCategoryCallback = false;
				}
				SonicPickupFiltersPlugin.DebugLog("Category options rebuilt count=" + list2.Count);
			}
		}

		private static void SetCategoryDropdownValue(int index)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			if ((Object)_categoryDropdown == (Object)null)
			{
				return;
			}
			_suppressCategoryCallback = true;
			try
			{
				_categoryDropdown.SetValueWithoutNotify(index);
			}
			finally
			{
				_suppressCategoryCallback = false;
			}
		}

		private static void FixDropdownOptionHits(Dropdown dropdown, float optionHeight)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_003b: 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)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_00ef: Expected O, but got Unknown
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Expected O, but got Unknown
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Expected O, but got Unknown
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Expected O, but got Unknown
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Expected O, but got Unknown
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Expected O, but got Unknown
			//IL_0283: 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_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)dropdown == (Object)null)
			{
				return;
			}
			if ((Object)dropdown.itemText != (Object)null)
			{
				RectTransform rectTransform = ((Graphic)dropdown.itemText).rectTransform;
				rectTransform.anchorMin = new Vector2(0f, 0f);
				rectTransform.anchorMax = new Vector2(1f, 1f);
				rectTransform.offsetMin = new Vector2(10f, 2f);
				rectTransform.offsetMax = new Vector2(-10f, -2f);
				((Graphic)dropdown.itemText).raycastTarget = false;
				dropdown.itemText.alignment = (TextAnchor)3;
			}
			if ((Object)dropdown.template == (Object)null)
			{
				return;
			}
			RectTransform template = dropdown.template;
			template.SetSizeWithCurrentAnchors((Axis)1, Mathf.Min(280f, optionHeight * 8f));
			Transform val = ((Transform)dropdown.template).Find("Viewport/Content");
			if ((Object)val != (Object)null)
			{
				VerticalLayoutGroup val2 = ((Component)val).GetComponent<VerticalLayoutGroup>() ?? ((Component)val).gameObject.AddComponent<VerticalLayoutGroup>();
				((LayoutGroup)val2).childAlignment = (TextAnchor)0;
				((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)val2).childForceExpandHeight = false;
				((HorizontalOrVerticalLayoutGroup)val2).childForceExpandWidth = true;
				((HorizontalOrVerticalLayoutGroup)val2).spacing = 0f;
				((LayoutGroup)val2).padding = new RectOffset(0, 0, 0, 0);
			}
			Transform val3 = ((Transform)dropdown.template).Find("Viewport/Content/Item");
			if ((Object)val3 == (Object)null)
			{
				return;
			}
			RectTransform val4 = (RectTransform)(object)((val3 is RectTransform) ? val3 : null);
			if ((Object)val4 != (Object)null)
			{
				val4.SetSizeWithCurrentAnchors((Axis)1, optionHeight);
			}
			LayoutElement val5 = ((Component)val3).GetComponent<LayoutElement>() ?? ((Component)val3).gameObject.AddComponent<LayoutElement>();
			val5.minHeight = optionHeight;
			val5.preferredHeight = optionHeight;
			val5.flexibleHeight = 0f;
			for (int i = 0; i < val3.childCount; i++)
			{
				Transform child = val3.GetChild(i);
				Image component = ((Component)child).GetComponent<Image>();
				if ((Object)component != (Object)null)
				{
					((Graphic)component).raycastTarget = true;
					RectTransform val6 = (RectTransform)(object)((child is RectTransform) ? child : null);
					if ((Object)val6 != (Object)null)
					{
						val6.anchorMin = Vector2.zero;
						val6.anchorMax = Vector2.one;
						val6.offsetMin = Vector2.zero;
						val6.offsetMax = Vector2.zero;
					}
				}
				Text component2 = ((Component)child).GetComponent<Text>();
				if ((Object)component2 != (Object)null)
				{
					((Graphic)component2).raycastTarget = false;
				}
			}
			Toggle component3 = ((Component)val3).GetComponent<Toggle>();
			if ((Object)component3 != (Object)null)
			{
				component3.toggleTransition = (ToggleTransition)0;
			}
		}

		private static void ClearContentChildren()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			if (!((Object)_contentRoot == (Object)null))
			{
				for (int num = ((Transform)_contentRoot).childCount - 1; num >= 0; num--)
				{
					Object.DestroyImmediate((Object)(object)((Component)((Transform)_contentRoot).GetChild(num)).gameObject);
				}
			}
		}

		private static void RefreshContent()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_00c6: 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_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			//IL_045f: Unknown result type (might be due to invalid IL or missing references)
			//IL_046e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0479: Expected O, but got Unknown
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Unknown result type (might be due to invalid IL or missing references)
			//IL_0515: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)_contentRoot == (Object)null)
			{
				return;
			}
			ClearContentChildren();
			List<ItemDrop> list = GetKnownItems();
			if (_viewTab == ViewTab.Blocked)
			{
				list = MergeRuleItems(list, PickupRuleMode.Block);
			}
			else if (_viewTab == ViewTab.Capped)
			{
				list = MergeRuleItems(list, PickupRuleMode.Cap);
			}
			UpdateTabLabels();
			IEnumerable<ItemDrop> source = list.Where((ItemDrop d) => ItemMatch.MatchesSearch(d, _searchText));
			bool flag = _viewTab == ViewTab.All && _categoryIndex > 0 && _categoryIndex < _categoryOptions.Count && _categoryOptions[_categoryIndex].HasValue;
			if (flag)
			{
				ItemType want = _categoryOptions[_categoryIndex].Value;
				source = source.Where((ItemDrop d) => GetItemType(d) == want);
			}
			if (_viewTab == ViewTab.Blocked)
			{
				source = source.Where((ItemDrop d) => PickupRuleStore.GetRule(PickupRuleStore.NormalizePrefabName(((Object)d).name)).Mode == PickupRuleMode.Block);
			}
			else if (_viewTab == ViewTab.Capped)
			{
				source = source.Where((ItemDrop d) => PickupRuleStore.GetRule(PickupRuleStore.NormalizePrefabName(((Object)d).name)).Mode == PickupRuleMode.Cap);
			}
			List<IGrouping<ItemType, ItemDrop>> list2 = (from g in source.GroupBy(GetItemType)
				orderby ItemMatch.FriendlyItemTypeLabel(g.Key)
				select g).ToList();
			int num = list2.Sum((IGrouping<ItemType, ItemDrop> g) => g.Select((ItemDrop d) => PickupRuleStore.NormalizePrefabName(((Object)d).name)).Distinct<string>(StringComparer.OrdinalIgnoreCase).Count());
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			SonicPickupFiltersPlugin.DebugLog($"Refresh tab={_viewTab} known={list.Count} items={num} search='{_searchText}' " + $"cat={_categoryIndex} applyCat={flag} rules={PickupRuleStore.CountByMode(PickupRuleMode.Block)}B/" + $"{PickupRuleStore.CountByMode(PickupRuleMode.Cap)}C");
			if (list2.Count == 0)
			{
				string text = ((_viewTab == ViewTab.Blocked || _viewTab == ViewTab.Capped) ? (((_viewTab == ViewTab.Blocked) ? (PickupRuleStore.CountByMode(PickupRuleMode.Block) > 0) : (PickupRuleStore.CountByMode(PickupRuleMode.Cap) > 0)) ? ((!string.IsNullOrEmpty(_searchText)) ? ("No matches for search \"" + _searchText + "\". Clear search to see all.") : ((_viewTab == ViewTab.Blocked) ? "No blocked items." : "No capped items.")) : ((_viewTab == ViewTab.Blocked) ? "No blocked items." : "No capped items.")) : ((list.Count != 0) ? "No matching items." : "No known items yet — pick something up first."));
				CreateContentLabel(text, 18, Color.white, 40f);
			}
			else
			{
				CreateColumnHeaderRow();
				float realtimeSinceStartup2 = Time.realtimeSinceStartup;
				foreach (IGrouping<ItemType, ItemDrop> item in list2)
				{
					List<ItemDrop> items = (from g in item.GroupBy<ItemDrop, string>((ItemDrop d) => PickupRuleStore.NormalizePrefabName(((Object)d).name), StringComparer.OrdinalIgnoreCase)
						select g.First() into d
						orderby ItemMatch.GetLocalized(d.m_itemData?.m_shared?.m_name)
						select d).ToList();
					CreateGroupSection(ItemMatch.FriendlyItemTypeLabel(item.Key), items);
				}
				SonicPickupFiltersPlugin.DebugLog($"Row build: {(Time.realtimeSinceStartup - realtimeSinceStartup2) * 1000f:F0}ms for {num} items");
			}
			float realtimeSinceStartup3 = Time.realtimeSinceStartup;
			Canvas.ForceUpdateCanvases();
			LayoutRebuilder.ForceRebuildLayoutImmediate(_contentRoot);
			float num2 = Mathf.Max(new float[3]
			{
				LayoutUtility.GetPreferredHeight(_contentRoot),
				EstimateContentHeight(list2),
				80f
			});
			_contentRoot.SetSizeWithCurrentAnchors((Axis)0, _contentWidth);
			_contentRoot.SetSizeWithCurrentAnchors((Axis)1, num2);
			_contentRoot.anchoredPosition = Vector2.zero;
			((Transform)_contentRoot).localScale = Vector3.one;
			if ((Object)_scrollRect != (Object)null)
			{
				_scrollRect.verticalNormalizedPosition = 1f;
			}
			string[] obj = new string[5]
			{
				$"Layout: {(Time.realtimeSinceStartup - realtimeSinceStartup3) * 1000f:F0}ms; ",
				$"total={(Time.realtimeSinceStartup - realtimeSinceStartup) * 1000f:F0}ms; ",
				$"children={((Transform)_contentRoot).childCount}; ",
				null,
				null
			};
			Rect rect = _contentRoot.rect;
			object arg = ((Rect)(ref rect)).width;
			rect = _contentRoot.rect;
			obj[3] = $"content={arg:F0}x{((Rect)(ref rect)).height:F0}; ";
			obj[4] = $"hasContentCanvas={(Object)(object)((Component)_contentRoot).GetComponent<Canvas>() != (Object)null}";
			SonicPickupFiltersPlugin.DebugLog(string.Concat(obj));
		}

		private static void CreateContentLabel(string text, int fontSize, Color color, float height)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("EmptyLabel", new Type[3]
			{
				typeof(RectTransform),
				typeof(Text),
				typeof(LayoutElement)
			});
			val.transform.SetParent((Transform)(object)_contentRoot, false);
			LayoutElement component = val.GetComponent<LayoutElement>();
			component.minHeight = height;
			component.preferredHeight = height;
			component.flexibleWidth = 1f;
			Text component2 = val.GetComponent<Text>();
			component2.font = GUIManager.Instance.AveriaSerifBold;
			component2.fontSize = fontSize;
			((Graphic)component2).color = color;
			component2.alignment = (TextAnchor)4;
			component2.text = text;
			GUIManager.Instance.ApplyTextStyle(component2, fontSize);
		}

		private static float EstimateContentHeight(List<IGrouping<ItemType, ItemDrop>> groups)
		{
			if (groups == null || groups.Count == 0)
			{
				return 80f;
			}
			float num = 44f;
			for (int i = 0; i < groups.Count; i++)
			{
				int num2 = groups[i].Select((ItemDrop d) => PickupRuleStore.NormalizePrefabName(((Object)d).name)).Distinct<string>(StringComparer.OrdinalIgnoreCase).Count();
				num += 22f + (float)num2 * 36f + 8f;
			}
			return num;
		}

		private static List<ItemDrop> MergeRuleItems(List<ItemDrop> known, PickupRuleMode mode)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			Dictionary<string, ItemDrop> dictionary = new Dictionary<string, ItemDrop>(StringComparer.OrdinalIgnoreCase);
			for (int i = 0; i < known.Count; i++)
			{
				string key = PickupRuleStore.NormalizePrefabName(((Object)known[i]).name);
				if (!dictionary.ContainsKey(key))
				{
					dictionary[key] = known[i];
				}
			}
			if ((Object)ObjectDB.instance != (Object)null)
			{
				foreach (KeyValuePair<string, PickupRule> item in PickupRuleStore.EnumerateRules())
				{
					if (item.Value.Mode != mode || dictionary.ContainsKey(item.Key))
					{
						continue;
					}
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.Key);
					if (!((Object)itemPrefab == (Object)null))
					{
						ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
						if ((Object)component != (Object)null)
						{
							dictionary[item.Key] = component;
						}
					}
				}
			}
			return dictionary.Values.ToList();
		}

		private static ItemType GetItemType(ItemDrop drop)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (drop?.m_itemData?.m_shared == null)
			{
				return (ItemType)16;
			}
			return drop.m_itemData.m_shared.m_itemType;
		}

		private static List<ItemDrop> GetKnownItems()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			List<ItemDrop> list = new List<ItemDrop>();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			if ((Object)ObjectDB.instance == (Object)null)
			{
				return list;
			}
			HashSet<string> hashSet2 = null;
			if ((Object)Player.m_localPlayer != (Object)null && KnownMaterialField != null)
			{
				hashSet2 = KnownMaterialField.GetValue(Player.m_localPlayer) as HashSet<string>;
			}
			foreach (GameObject item2 in ObjectDB.instance.m_items)
			{
				if ((Object)item2 == (Object)null)
				{
					continue;
				}
				ItemDrop component = item2.GetComponent<ItemDrop>();
				if ((Object)component == (Object)null || component.m_itemData?.m_shared == null)
				{
					continue;
				}
				string item = PickupRuleStor