Decompiled source of ChestItemFilter v1.0.0

BepInEx/plugins/ChestItemFilter/ChestItemFilter.dll

Decompiled 15 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ChestItemFilter")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+627c93de35fe4ea8fc7db780adf6d890daf2a24a")]
[assembly: AssemblyProduct("ChestItemFilter")]
[assembly: AssemblyTitle("ChestItemFilter")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace VanillaChestItemCategory;

[BepInPlugin("dellarion.valheim.vanillachestitemcategory", "ChestItemFilter", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Guid = "dellarion.valheim.vanillachestitemcategory";

	public const string Version = "1.0.0";

	internal static ConfigEntry<bool> Enabled;

	internal static ConfigEntry<bool> ShowFilterButton;

	internal static ConfigEntry<bool> FilterRadiusIntegrationEnabled;

	internal static ConfigEntry<bool> ShowUndiscoveredItems;

	internal static ConfigEntry<bool> BlockManualInvalidItems;

	internal static ManualLogSource Log;

	private Harmony harmony;

	private void Awake()
	{
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable storage item filters on this peer.");
		ShowFilterButton = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface", "ShowFilterButton", true, "Show the filter button for supported storage.");
		FilterRadiusIntegrationEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "FilterRadiusIntegrationEnabled", true, "Enable destination priorities and empty filtered chests in supported nearby sorters. Admission remains enforced.");
		ShowUndiscoveredItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface", "ShowUndiscoveredItems", false, "Show undiscovered inventory items. Does not reveal internal objects.");
		BlockManualInvalidItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "BlockManualInvalidItems", true, "Reject incompatible manual drops. Disable only for a conflicting inventory UI. Automatic admission stays enabled.");
		UiTheme.Load();
		harmony = new Harmony("dellarion.valheim.vanillachestitemcategory");
		harmony.PatchAll(typeof(Plugin).Assembly);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ChestItemFilter 1.0.0 loaded. Install on all participating peers and server.");
	}

	private void LateUpdate()
	{
		StorageFilterUi.Tick();
	}

	private void OnDestroy()
	{
		StorageFilterUi.Dispose();
		StorageFilterPersistence.Dispose();
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}
}
public sealed class StorageFilter
{
	public const int CurrentVersion = 2;

	public const int MaximumPayloadLength = 65536;

	private readonly HashSet<string> allowed;

	public bool Enabled { get; }

	public int Version { get; }

	public IReadOnlyList<string> PrefabIds { get; }

	public StorageFilter(bool enabled, string itemA, string itemB, int version = 2)
		: this(enabled, new string[2] { itemA, itemB }, version)
	{
	}

	public StorageFilter(bool enabled, IEnumerable<string> ids, int version = 2)
	{
		Enabled = enabled;
		Version = version;
		PrefabIds = Array.AsReadOnly(ids.Where((string id) => !string.IsNullOrEmpty(id)).Distinct<string>(StringComparer.Ordinal).ToArray());
		allowed = new HashSet<string>(PrefabIds, StringComparer.Ordinal);
	}

	public bool Accepts(string prefabId)
	{
		return !Enabled || ((Version == 1 || Version == 2) && !string.IsNullOrEmpty(prefabId) && allowed.Contains(prefabId));
	}

	public int Priority(string prefabId)
	{
		if (!Enabled)
		{
			return 2;
		}
		if (!Accepts(prefabId))
		{
			return int.MaxValue;
		}
		return (!string.Equals(PrefabIds[0], prefabId, StringComparison.Ordinal)) ? 1 : 0;
	}

	public static bool TryNormalize(IEnumerable<string> values, out string[] ids)
	{
		ids = Array.Empty<string>();
		if (values == null)
		{
			return false;
		}
		List<string> list = new List<string>();
		HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
		int num = 0;
		foreach (string value in values)
		{
			if (!ValidId(value))
			{
				return false;
			}
			if (hashSet.Add(value))
			{
				num += value.Length + ((list.Count != 0) ? 1 : 0);
				if (num > 65536)
				{
					return false;
				}
				list.Add(value);
			}
		}
		ids = list.ToArray();
		return true;
	}

	public static bool TryDecode(string payload, out string[] ids)
	{
		ids = Array.Empty<string>();
		if (payload == null || payload.Length > 65536)
		{
			return false;
		}
		return payload.Length == 0 || TryNormalize(payload.Split('\n'), out ids);
	}

	public static bool ValidId(string value)
	{
		return !string.IsNullOrWhiteSpace(value) && value.Length <= 256 && value == value.Trim() && !value.Any(char.IsControl) && !value.Contains("(Clone)");
	}
}
public static class CatalogRules
{
	public static bool Visible(bool discovered, bool showUndiscovered, bool hasIcon, string itemType, int maxStack, string sharedName)
	{
		return (discovered || showUndiscovered) && hasIcon && maxStack > 0 && !string.IsNullOrWhiteSpace(sharedName) && itemType != "None" && itemType != "Customization";
	}

	public static string Category(string type)
	{
		switch (type)
		{
		case "Material":
			return "materials";
		case "Consumable":
		case "Fish":
			return "food";
		case "Tool":
		case "Torch":
			return "tools";
		case "Misc":
		case "Trophy":
			return "other";
		default:
			return "equipment";
		}
	}

	public static bool Matches(string id, string name, string category, string selectedCategory, string search)
	{
		return (selectedCategory == "all" || category == selectedCategory) && (string.IsNullOrWhiteSpace(search) || id.IndexOf(search.Trim(), StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf(search.Trim(), StringComparison.OrdinalIgnoreCase) >= 0);
	}
}
public static class StorageFilterCore
{
	private static readonly HashSet<string> Supported = new HashSet<string>(StringComparer.Ordinal) { "piece_chest_wood", "piece_chest", "piece_chest_blackmetal", "piece_chest_private", "piece_chest_barrel" };

	public static void RegisterContainerPrefab(string prefabId)
	{
		if (!StorageFilter.ValidId(prefabId))
		{
			throw new ArgumentException("Invalid prefab ID", "prefabId");
		}
		Supported.Add(prefabId);
	}

	public static bool IsSupported(Container container)
	{
		if (!Object.op_Implicit((Object)(object)container) || Object.op_Implicit((Object)(object)((Component)container).GetComponentInParent<Ship>()) || Object.op_Implicit((Object)(object)((Component)container).GetComponentInParent<Vagon>()) || Object.op_Implicit((Object)(object)((Component)container).GetComponentInParent<TombStone>()))
		{
			return false;
		}
		ZNetView component = ((Component)container).GetComponent<ZNetView>();
		return Object.op_Implicit((Object)(object)component) && component.IsValid() && Supported.Contains(Utils.GetPrefabName(((Component)container).gameObject)) && container.GetInventory() != null;
	}

	public static string PrefabId(ItemData item)
	{
		return Object.op_Implicit((Object)(object)item?.m_dropPrefab) ? ((Object)item.m_dropPrefab).name : null;
	}

	public static bool CanAcceptItem(Container container, ItemData item)
	{
		StorageFilter filter;
		return !Plugin.Enabled.Value || !TryGetFilter(container, out filter) || filter.Accepts(PrefabId(item));
	}

	public static bool TryGetFilter(Container container, out StorageFilter filter)
	{
		filter = null;
		if (!IsSupported(container))
		{
			return false;
		}
		filter = StorageFilterPersistence.Read(((Component)container).GetComponent<ZNetView>().GetZDO());
		return filter.Enabled;
	}

	public static bool SetFilter(Container container, IEnumerable<string> prefabIds)
	{
		return StorageFilterPersistence.Request(container, prefabIds);
	}

	public static void ClearFilter(Container container)
	{
		SetFilter(container, Array.Empty<string>());
	}
}
internal static class Admission
{
	[ThreadStatic]
	internal static int Loading;

	[ThreadStatic]
	internal static int Manual;

	internal static bool Allows(Inventory inventory, MethodBase method, object[] args)
	{
		if (Loading > 0 || !Plugin.Enabled.Value || !StorageFilterPersistence.Containers.TryGetValue(inventory, out var value))
		{
			return true;
		}
		if (!StorageFilterCore.TryGetFilter(value, out var _))
		{
			return true;
		}
		if (method.Name == "AddItem" && !StorageFilterPersistence.CanMutate(value))
		{
			return false;
		}
		if (Manual > 0 && !Plugin.BlockManualInvalidItems.Value)
		{
			return true;
		}
		ItemData val = args.OfType<ItemData>().FirstOrDefault();
		if (val == null)
		{
			GameObject val2 = args.OfType<GameObject>().FirstOrDefault();
			if (!Object.op_Implicit((Object)(object)val2) && args.Length != 0 && args[0] is string text && Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				val2 = ObjectDB.instance.GetItemPrefab(text);
			}
			if (!Object.op_Implicit((Object)(object)val2) && args.Length != 0 && args[0] is int num && Object.op_Implicit((Object)(object)ObjectDB.instance) && method.GetParameters()[0].Name == "prefabHash")
			{
				val2 = ObjectDB.instance.GetItemPrefab(num);
			}
			val = ((!Object.op_Implicit((Object)(object)val2)) ? null : val2.GetComponent<ItemDrop>()?.m_itemData);
			if (val != null && !Object.op_Implicit((Object)(object)val.m_dropPrefab))
			{
				val = val.Clone();
				val.m_dropPrefab = val2;
			}
		}
		if (val != null && inventory.ContainsItem(val))
		{
			return true;
		}
		bool flag = StorageFilterCore.CanAcceptItem(value, val);
		if (!flag && Manual > 0)
		{
			StorageFilterUi.RejectedMessage();
		}
		return flag;
	}

	internal static bool AllowsDrop(Inventory destination, Inventory source, ItemData item, Vector2i position)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		if (!Plugin.Enabled.Value)
		{
			return true;
		}
		ItemData itemAt = destination.GetItemAt(position.x, position.y);
		if (destination == source)
		{
			return true;
		}
		if (!Accepts(destination, item) || (itemAt != null && !itemAt.IsSameType(item) && !Accepts(source, itemAt)))
		{
			StorageFilterUi.RejectedMessage();
			return false;
		}
		return true;
		static bool Accepts(Inventory inventory, ItemData candidate)
		{
			Container value;
			StorageFilter filter;
			return !StorageFilterPersistence.Containers.TryGetValue(inventory, out value) || ((!StorageFilterCore.TryGetFilter(value, out filter) || StorageFilterPersistence.CanMutate(value)) && (!Plugin.BlockManualInvalidItems.Value || StorageFilterCore.CanAcceptItem(value, candidate)));
		}
	}

	internal static bool AllowsMove(Inventory destination, Inventory source, ItemData item, int amount = int.MaxValue)
	{
		if (!Plugin.Enabled.Value || Loading > 0)
		{
			return true;
		}
		if (source == null || destination == null)
		{
			return false;
		}
		Container value;
		StorageFilter filter;
		bool flag = StorageFilterPersistence.Containers.TryGetValue(source, out value) && StorageFilterCore.TryGetFilter(value, out filter);
		Container value2;
		bool flag2 = StorageFilterPersistence.Containers.TryGetValue(destination, out value2) && StorageFilterCore.TryGetFilter(value2, out filter);
		if (!flag && !flag2)
		{
			return true;
		}
		return amount > 0 && item != null && source.ContainsItem(item) && (!flag || StorageFilterPersistence.CanMutate(value)) && (!flag2 || StorageFilterPersistence.CanMutate(value2));
	}
}
[HarmonyPatch(typeof(Container), "Awake")]
internal static class ContainerRegisterPatch
{
	private static void Postfix(Container __instance)
	{
		StorageFilterPersistence.Register(__instance);
		if (StorageFilterCore.IsSupported(__instance))
		{
			((Component)__instance).gameObject.AddComponent<StorageFilterBinding>().Container = __instance;
		}
	}
}
internal sealed class StorageFilterBinding : MonoBehaviour
{
	internal Container Container;

	private void OnDestroy()
	{
		StorageFilterPersistence.Unregister(Container);
	}
}
[HarmonyPatch(typeof(Container), "OnDestroyed")]
internal static class ContainerDestroyedPatch
{
	private static void Prefix(Container __instance)
	{
		StorageFilterPersistence.Unregister(__instance);
	}
}
[HarmonyPatch]
internal static class TransferRequestPatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return new MethodInfo[2]
		{
			AccessTools.Method(typeof(Container), "RPC_RequestOpen", (Type[])null, (Type[])null),
			AccessTools.Method(typeof(Container), "RPC_RequestStack", (Type[])null, (Type[])null)
		};
	}

	private static bool Prefix(Container __instance, long __0, long __1, MethodBase __originalMethod)
	{
		if (!Plugin.Enabled.Value || !StorageFilterCore.TryGetFilter(__instance, out var _))
		{
			return true;
		}
		ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
		if (!component.IsOwner() || StorageFilterPersistence.AuthorizeTransfer(__instance, __0, __1))
		{
			return true;
		}
		component.InvokeRPC(__0, (__originalMethod.Name == "RPC_RequestOpen") ? "RPC_OpenResponse" : "RPC_StackResponse", new object[1] { false });
		return false;
	}
}
[HarmonyPatch]
internal static class BooleanAdmissionPatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return from m in AccessTools.GetDeclaredMethods(typeof(Inventory))
			where (m.Name == "AddItem" || m.Name == "CanAddItem") && m.ReturnType == typeof(bool)
			select m;
	}

	[HarmonyPriority(800)]
	private static bool Prefix(Inventory __instance, MethodBase __originalMethod, object[] __args, ref bool __result)
	{
		if (Admission.Allows(__instance, __originalMethod, __args))
		{
			return true;
		}
		__result = false;
		return false;
	}
}
[HarmonyPatch]
internal static class ItemAdmissionPatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return from m in AccessTools.GetDeclaredMethods(typeof(Inventory))
			where m.Name == "AddItem" && m.ReturnType == typeof(ItemData)
			select m;
	}

	private static bool Prefix(Inventory __instance, MethodBase __originalMethod, object[] __args, ref ItemData __result)
	{
		if (Admission.Allows(__instance, __originalMethod, __args))
		{
			return true;
		}
		__result = null;
		return false;
	}
}
[HarmonyPatch]
internal static class WholeMovePatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return from m in AccessTools.GetDeclaredMethods(typeof(Inventory))
			where m.Name == "MoveItemToThis" && m.ReturnType == typeof(void)
			select m;
	}

	private static bool Prefix(Inventory __instance, Inventory __0, ItemData __1)
	{
		return Admission.AllowsMove(__instance, __0, __1);
	}
}
[HarmonyPatch]
internal static class AmountMovePatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return from m in AccessTools.GetDeclaredMethods(typeof(Inventory))
			where m.Name == "MoveItemToThis" && m.ReturnType == typeof(bool)
			select m;
	}

	private static bool Prefix(Inventory __instance, Inventory __0, ItemData __1, int __2, ref bool __result)
	{
		if (Admission.AllowsMove(__instance, __0, __1, __2))
		{
			return true;
		}
		__result = false;
		return false;
	}
}
[HarmonyPatch]
internal static class LoadPatch
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		return from m in AccessTools.GetDeclaredMethods(typeof(Inventory))
			where m.Name == "Load" || m.Name == "LoadOld"
			select m;
	}

	private static void Prefix(out bool __state)
	{
		Admission.Loading++;
		__state = true;
	}

	private static Exception Finalizer(Exception __exception, bool __state)
	{
		if (__state)
		{
			Admission.Loading--;
		}
		return __exception;
	}
}
[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
internal static class DropPatch
{
	[HarmonyPriority(800)]
	private static bool Prefix(Inventory ___m_inventory, Inventory __0, ItemData __1, Vector2i __3, ref bool __result, out bool __state)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		__state = false;
		if (__1 == null || !Admission.AllowsDrop(___m_inventory, __0, __1, __3))
		{
			__result = false;
			return false;
		}
		Admission.Manual++;
		__state = true;
		return true;
	}

	private static Exception Finalizer(Exception __exception, bool __state)
	{
		if (__state)
		{
			Admission.Manual--;
		}
		return __exception;
	}
}
[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
internal static class ManualSelectionPatch
{
	private static void Prefix(out bool __state)
	{
		Admission.Manual++;
		__state = true;
	}

	private static Exception Finalizer(Exception __exception, bool __state)
	{
		if (__state)
		{
			Admission.Manual--;
		}
		return __exception;
	}
}
[HarmonyPatch(typeof(InventoryGui), "Update")]
internal static class ModalInputPatch
{
	private static bool Prefix()
	{
		if (!StorageFilterUi.IsOpen)
		{
			return true;
		}
		if (Input.GetKeyDown((KeyCode)27) || ZInput.GetButtonDown("JoyButtonB"))
		{
			StorageFilterUi.Close();
		}
		return false;
	}
}
[HarmonyPatch(typeof(InventoryGui), "Hide")]
internal static class CloseUiPatch
{
	private static void Prefix()
	{
		StorageFilterUi.Close();
	}
}
public static class StorageFilterCompatibility
{
	public static bool CanAcceptItem(Container container, ItemData item)
	{
		return StorageFilterCore.CanAcceptItem(container, item);
	}

	public static bool TryGetFilter(Container container, out StorageFilter filter)
	{
		return StorageFilterCore.TryGetFilter(container, out filter);
	}

	public static bool SetFilter(Container container, IEnumerable<string> ids)
	{
		return StorageFilterCore.SetFilter(container, ids);
	}

	public static void ClearFilter(Container container)
	{
		StorageFilterCore.ClearFilter(container);
	}

	internal static bool ContainsItemOrFilter(Inventory inventory, string sharedName)
	{
		if (Plugin.Enabled.Value && Plugin.FilterRadiusIntegrationEnabled.Value && StorageFilterPersistence.Containers.TryGetValue(inventory, out var value) && StorageFilterCore.TryGetFilter(value, out var filter))
		{
			foreach (string prefabId in filter.PrefabIds)
			{
				GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(prefabId) : null);
				ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null);
				if (Object.op_Implicit((Object)(object)val2) && val2.m_itemData.m_shared.m_name == sharedName)
				{
					return true;
				}
			}
		}
		return inventory.ContainsItemByName(sharedName);
	}
}
[HarmonyPatch(typeof(Inventory), "StackAll")]
internal static class StackAllDestinationPatch
{
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		MethodInfo original = AccessTools.Method(typeof(Inventory), "ContainsItemByName", (Type[])null, (Type[])null);
		MethodInfo replacement = AccessTools.Method(typeof(StorageFilterCompatibility), "ContainsItemOrFilter", (Type[])null, (Type[])null);
		int found = 0;
		foreach (CodeInstruction instruction in instructions)
		{
			if (CodeInstructionExtensions.Calls(instruction, original))
			{
				instruction.opcode = OpCodes.Call;
				instruction.operand = replacement;
				found++;
			}
			yield return instruction;
		}
		if (found != 1)
		{
			throw new InvalidOperationException("Inventory.StackAll destination check changed; refusing an unsafe patch.");
		}
	}
}
internal static class StorageFilterHover
{
	private sealed class Entry
	{
		internal StorageFilter Filter;

		internal string Language;

		internal string Text;

		internal string BaseText;

		internal string CombinedFilter;

		internal string Combined;

		internal ObjectDB Database;

		internal int ItemCount;
	}

	private static readonly ConditionalWeakTable<Container, Entry> Cache = new ConditionalWeakTable<Container, Entry>();

	private static readonly ConditionalWeakTable<Container, Entry>.CreateValueCallback NewEntry = (Container _) => new Entry();

	internal static string Describe(Container container)
	{
		if (!Plugin.Enabled.Value || !StorageFilterCore.TryGetFilter(container, out var filter) || filter.PrefabIds.Count == 0)
		{
			return null;
		}
		Localization instance = Localization.instance;
		string text = ((instance != null) ? instance.GetSelectedLanguage() : null);
		ObjectDB instance2 = ObjectDB.instance;
		int num = (Object.op_Implicit((Object)(object)instance2) ? instance2.m_items.Count : 0);
		Entry value = Cache.GetValue(container, NewEntry);
		if (value.Filter == filter && value.Language == text && (Object)(object)value.Database == (Object)(object)instance2 && value.ItemCount == num)
		{
			return value.Text;
		}
		value.Text = string.Format(Texts.Get("hoverfilter"), string.Join(", ", filter.PrefabIds.Select(ItemCatalog.DisplayName)));
		value.Filter = filter;
		value.Language = text;
		value.Database = instance2;
		value.ItemCount = num;
		return value.Text;
	}

	internal static string Append(Container container, string original)
	{
		string text = Describe(container);
		if (text == null)
		{
			return original;
		}
		Entry value = Cache.GetValue(container, NewEntry);
		if (value.BaseText == original && (object)value.CombinedFilter == text && value.Combined != null)
		{
			return value.Combined;
		}
		value.BaseText = original;
		value.CombinedFilter = text;
		value.Combined = (string.IsNullOrEmpty(original) ? text : (original + "\n" + text));
		return value.Combined;
	}
}
[HarmonyPatch(typeof(Container), "GetHoverText")]
internal static class FilterHoverPatch
{
	private static void Postfix(Container __instance, ref string __result)
	{
		__result = StorageFilterHover.Append(__instance, __result);
	}
}
public static class StorageFilterPersistence
{
	private sealed class CachedFilter
	{
		internal string A;

		internal string B;

		internal string Items;

		internal int Version;

		internal bool Enabled;

		internal StorageFilter Value;
	}

	public const string EnabledKey = "StorageFilter.Enabled";

	public const string ItemAKey = "StorageFilter.ItemA";

	public const string ItemBKey = "StorageFilter.ItemB";

	public const string VersionKey = "StorageFilter.Version";

	public const string ItemsKey = "StorageFilter.Items";

	private const string RequestRpc = "VCIC_SetFilterV2";

	private const string ResultRpc = "VCIC_FilterResultV2";

	private const float EditRange = 10f;

	private static readonly Func<Container, long, bool> CheckAccess = AccessTools.MethodDelegate<Func<Container, long, bool>>(AccessTools.Method(typeof(Container), "CheckAccess", (Type[])null, (Type[])null), (object)null, true);

	private static readonly Func<PrivateArea, bool> WardEnabled = AccessTools.MethodDelegate<Func<PrivateArea, bool>>(AccessTools.Method(typeof(PrivateArea), "IsEnabled", (Type[])null, (Type[])null), (object)null, true);

	private static readonly Func<PrivateArea, Vector3, float, bool> WardInside = AccessTools.MethodDelegate<Func<PrivateArea, Vector3, float, bool>>(AccessTools.Method(typeof(PrivateArea), "IsInside", (Type[])null, (Type[])null), (object)null, true);

	private static readonly Func<PrivateArea, long, bool> WardPermitted = AccessTools.MethodDelegate<Func<PrivateArea, long, bool>>(AccessTools.Method(typeof(PrivateArea), "IsPermitted", (Type[])null, (Type[])null), (object)null, true);

	private static readonly FieldInfo AllWards = AccessTools.Field(typeof(PrivateArea), "m_allAreas");

	internal static readonly Dictionary<Inventory, Container> Containers = new Dictionary<Inventory, Container>();

	private static readonly Dictionary<Container, int> Pending = new Dictionary<Container, int>();

	private static int nextRequest;

	private static readonly ConditionalWeakTable<ZDO, CachedFilter> Cache = new ConditionalWeakTable<ZDO, CachedFilter>();

	private static readonly ConditionalWeakTable<ZDO, CachedFilter>.CreateValueCallback CreateCache = (ZDO _) => new CachedFilter();

	public static event Action<Container, bool> Completed;

	public static StorageFilter Read(ZDO zdo)
	{
		int num = zdo.GetInt("StorageFilter.Version", 1);
		bool flag = zdo.GetBool("StorageFilter.Enabled", false);
		string text = ((num == 1) ? zdo.GetString("StorageFilter.ItemA", "") : "");
		string text2 = ((num == 1) ? zdo.GetString("StorageFilter.ItemB", "") : "");
		string text3 = ((num == 1) ? "" : zdo.GetString("StorageFilter.Items", ""));
		CachedFilter value = Cache.GetValue(zdo, CreateCache);
		if (value.Value != null && value.Version == num && value.Enabled == flag && value.A == text && value.B == text2 && value.Items == text3)
		{
			return value.Value;
		}
		string[] ids2;
		string[] ids = ((num != 1) ? (StorageFilter.TryDecode(text3, out ids2) ? ids2 : Array.Empty<string>()) : new string[2] { text, text2 });
		value.Value = new StorageFilter(flag, ids, num);
		value.Version = num;
		value.Enabled = flag;
		value.A = text;
		value.B = text2;
		value.Items = text3;
		return value.Value;
	}

	internal static void Register(Container container)
	{
		if (!StorageFilterCore.IsSupported(container))
		{
			return;
		}
		Containers[container.GetInventory()] = container;
		ZNetView view = ((Component)container).GetComponent<ZNetView>();
		view.Register<string, string, int>("VCIC_SetFilterV2", (Action<long, string, string, int>)delegate(long sender, string payload, string expected, int requestId)
		{
			bool flag = Apply(container, sender, payload, expected);
			if (view.IsValid() && view.IsOwner())
			{
				view.InvokeRPC(sender, "VCIC_FilterResultV2", new object[2] { requestId, flag });
			}
		});
		view.Register<int, bool>("VCIC_FilterResultV2", (Action<long, int, bool>)delegate(long sender, int requestId, bool accepted)
		{
			if (view.IsValid() && sender == view.GetZDO().GetOwner() && Pending.TryGetValue(container, out var value) && value == requestId)
			{
				Pending.Remove(container);
				StorageFilterPersistence.Completed?.Invoke(container, accepted);
			}
		});
	}

	internal static void Unregister(Container container)
	{
		KeyValuePair<Inventory, Container>[] array = Containers.Where((KeyValuePair<Inventory, Container> pair) => pair.Value == container).ToArray();
		foreach (KeyValuePair<Inventory, Container> keyValuePair in array)
		{
			Containers.Remove(keyValuePair.Key);
		}
		if (container != null)
		{
			Pending.Remove(container);
		}
		ZNetView val = (Object.op_Implicit((Object)(object)container) ? ((Component)container).GetComponent<ZNetView>() : null);
		if (Object.op_Implicit((Object)(object)val) && val.IsValid())
		{
			val.Unregister("VCIC_SetFilterV2");
			val.Unregister("VCIC_FilterResultV2");
		}
	}

	internal static string Snapshot(Container container)
	{
		StorageFilter storageFilter = Read(((Component)container).GetComponent<ZNetView>().GetZDO());
		return storageFilter.Version.ToString(CultureInfo.InvariantCulture) + ":" + storageFilter.Enabled + ":" + string.Join("\n", storageFilter.PrefabIds);
	}

	public static bool Request(Container container, IEnumerable<string> values)
	{
		if (!Plugin.Enabled.Value || !StorageFilterCore.IsSupported(container) || !StorageFilter.TryNormalize(values, out var ids) || !CanAccess(container, Player.m_localPlayer, 10f))
		{
			return false;
		}
		ZNetView component = ((Component)container).GetComponent<ZNetView>();
		string text = string.Join("\n", ids);
		string text2 = Snapshot(container);
		long uID = ZNet.GetUID();
		if (component.IsOwner())
		{
			bool flag = Apply(container, uID, text, text2);
			StorageFilterPersistence.Completed?.Invoke(container, flag);
			return flag;
		}
		int num = ++nextRequest;
		Pending[container] = num;
		component.InvokeRPC(component.GetZDO().GetOwner(), "VCIC_SetFilterV2", new object[3] { text, text2, num });
		return true;
	}

	private static Player SenderPlayer(long sender)
	{
		return ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)delegate(Player player)
		{
			ZNetView val = (Object.op_Implicit((Object)(object)player) ? ((Component)player).GetComponent<ZNetView>() : null);
			return Object.op_Implicit((Object)(object)val) && val.IsValid() && val.GetZDO().GetOwner() == sender;
		});
	}

	internal static bool AuthorizeTransfer(Container container, long sender, long claimedPlayerId)
	{
		Player val = SenderPlayer(sender);
		return Object.op_Implicit((Object)(object)val) && val.GetPlayerID() == claimedPlayerId && CanAccess(container, val);
	}

	private static bool Apply(Container container, long sender, string payload, string expected)
	{
		if (!Plugin.Enabled.Value || !StorageFilterCore.IsSupported(container))
		{
			return false;
		}
		ZNetView component = ((Component)container).GetComponent<ZNetView>();
		Player player = SenderPlayer(sender);
		if (!component.IsOwner() || !CanAccess(container, player, 10f) || (container.IsInUse() && sender != component.GetZDO().GetOwner()) || Snapshot(container) != expected || !StorageFilter.TryDecode(payload, out var ids))
		{
			return false;
		}
		StorageFilter storageFilter = Read(component.GetZDO());
		string[] array = ids;
		foreach (string text in array)
		{
			if (!storageFilter.PrefabIds.Contains(text) && !ItemCatalog.IsInventoryItem(text))
			{
				return false;
			}
		}
		ZDO zDO = component.GetZDO();
		zDO.Set("StorageFilter.Items", string.Join("\n", ids));
		zDO.Set("StorageFilter.ItemA", ids.ElementAtOrDefault(0) ?? "");
		zDO.Set("StorageFilter.ItemB", ids.ElementAtOrDefault(1) ?? "");
		zDO.Set("StorageFilter.Version", 2);
		zDO.Set("StorageFilter.Enabled", ids.Length != 0);
		return true;
	}

	internal static bool CanAccess(Container container, Player player, float range = float.PositiveInfinity)
	{
		//IL_002a: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)player) || !CheckAccess(container, player.GetPlayerID()) || Vector3.Distance(((Component)container).transform.position, ((Component)player).transform.position) > range)
		{
			return false;
		}
		if (!container.m_checkGuardStone)
		{
			return true;
		}
		bool flag = false;
		foreach (PrivateArea item in (List<PrivateArea>)AllWards.GetValue(null))
		{
			if (Object.op_Implicit((Object)(object)item) && WardEnabled(item) && WardInside(item, ((Component)container).transform.position, 0f))
			{
				flag = true;
				Piece component = ((Component)item).GetComponent<Piece>();
				if ((Object.op_Implicit((Object)(object)component) && component.GetCreator() == player.GetPlayerID()) || WardPermitted(item, player.GetPlayerID()))
				{
					return true;
				}
			}
		}
		return !flag;
	}

	internal static bool CanMutate(Container container)
	{
		ZNetView val = (Object.op_Implicit((Object)(object)container) ? ((Component)container).GetComponent<ZNetView>() : null);
		if (!Object.op_Implicit((Object)(object)val) || !val.IsValid() || !val.IsOwner() || !CanAccess(container, Player.m_localPlayer))
		{
			return false;
		}
		return !container.IsInUse() || (Object)(object)StorageFilterUi.CurrentContainer == (Object)(object)container;
	}

	internal static void Dispose()
	{
		Container[] array = Containers.Values.ToArray();
		foreach (Container val in array)
		{
			if (Object.op_Implicit((Object)(object)val))
			{
				Unregister(val);
			}
		}
		Containers.Clear();
		Pending.Clear();
	}
}
public static class StorageFilterRouting
{
	public static int Priority(Container container, ItemData item)
	{
		if (!Plugin.Enabled.Value || !Plugin.FilterRadiusIntegrationEnabled.Value || !StorageFilterCore.TryGetFilter(container, out var filter))
		{
			return 2;
		}
		return filter.Priority(StorageFilterCore.PrefabId(item));
	}

	public static IEnumerable<Container> OrderDestinations(IEnumerable<Container> containers, ItemData item, Vector3 origin)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		return (from c in containers
			where Object.op_Implicit((Object)(object)c) && StorageFilterCore.CanAcceptItem(c, item)
			orderby Priority(c, item), Vector3.SqrMagnitude(((Component)c).transform.position - origin)
			select c).ThenBy<Container, string>((Container c) => ((object)Unsafe.As<ZDOID, ZDOID>(ref ((Component)c).GetComponent<ZNetView>().GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString(), StringComparer.Ordinal);
	}

	public static bool IsExplicitDestination(Container container, ItemData item)
	{
		StorageFilter filter;
		return Plugin.Enabled.Value && Plugin.FilterRadiusIntegrationEnabled.Value && StorageFilterCore.TryGetFilter(container, out filter) && StorageFilterCore.CanAcceptItem(container, item);
	}
}
internal sealed class FilterTooltip : MonoBehaviour
{
	internal bool Header;
}
internal static class FilterTooltips
{
	private static GameObject display;

	private static GameObject topic;

	private static RectTransform panel;

	private static Canvas canvas;

	private static Vector3 originalPosition;

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

	private static bool positioned;

	private static bool originalActive;

	private static bool hidden;

	internal static void Set(UITooltip tooltip, string text)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		FilterTooltip filterTooltip = ((Component)tooltip).GetComponent<FilterTooltip>() ?? ((Component)tooltip).gameObject.AddComponent<FilterTooltip>();
		filterTooltip.Header = false;
		tooltip.Set("", text, (RectTransform)null, Vector2.zero);
	}

	internal static void SetHeader(UITooltip tooltip, string text)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		FilterTooltip filterTooltip = ((Component)tooltip).GetComponent<FilterTooltip>() ?? ((Component)tooltip).gameObject.AddComponent<FilterTooltip>();
		filterTooltip.Header = true;
		tooltip.Set(text, "", (RectTransform)null, Vector2.zero);
	}

	internal static void Refresh(UITooltip owner, GameObject currentDisplay)
	{
		if (Object.op_Implicit((Object)(object)currentDisplay))
		{
			if ((Object)(object)display != (Object)(object)currentDisplay)
			{
				Reset();
				display = currentDisplay;
				Transform val = Utils.FindChild(display.transform, "Topic", (IterativeSearchType)0);
				topic = (Object.op_Implicit((Object)(object)val) ? ((Component)val).gameObject : null);
				originalActive = Object.op_Implicit((Object)(object)topic) && topic.activeSelf;
				panel = (RectTransform)((display.transform.childCount > 0) ? /*isinst with value type is only supported in some contexts*/: null);
				canvas = ((Component)owner).GetComponentInParent<Canvas>();
			}
			FilterTooltip component = ((Component)owner).GetComponent<FilterTooltip>();
			bool flag = Object.op_Implicit((Object)(object)component) && component.Header;
			if (!flag)
			{
				RestorePosition();
			}
			bool flag2 = (Object.op_Implicit((Object)(object)component) ? flag : originalActive);
			if (Object.op_Implicit((Object)(object)topic) && topic.activeSelf != flag2)
			{
				topic.SetActive(flag2);
			}
			hidden = flag2 != originalActive;
		}
	}

	internal static Vector3 CursorShift(Vector3 cursor, Vector3 topLeft, float scale)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: 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)
		return new Vector3(cursor.x + UiTheme.Current.tooltipCursorOffsetX * scale - topLeft.x, cursor.y - UiTheme.Current.tooltipCursorOffsetY * scale - topLeft.y, 0f);
	}

	internal static void FollowCursor(UITooltip owner, GameObject currentDisplay)
	{
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: 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_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_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: 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)
		FilterTooltip component = ((Component)owner).GetComponent<FilterTooltip>();
		if (!Object.op_Implicit((Object)(object)component) || !component.Header || !Object.op_Implicit((Object)(object)currentDisplay) || !currentDisplay.activeSelf)
		{
			return;
		}
		if ((Object)(object)display != (Object)(object)currentDisplay)
		{
			Refresh(owner, currentDisplay);
		}
		if (Object.op_Implicit((Object)(object)panel))
		{
			if (!positioned)
			{
				originalPosition = ((Transform)panel).localPosition;
				positioned = true;
			}
			panel.GetWorldCorners(Corners);
			Vector3 val = CursorShift(ZInput.pointerPosition, Corners[1], Object.op_Implicit((Object)(object)canvas) ? canvas.scaleFactor : 1f);
			if (val.x != 0f || val.y != 0f)
			{
				RectTransform obj = panel;
				((Transform)obj).position = ((Transform)obj).position + val;
			}
			Utils.ClampUIToScreen(panel);
		}
	}

	internal static void RestorePosition()
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		if (positioned && Object.op_Implicit((Object)(object)panel))
		{
			((Transform)panel).localPosition = originalPosition;
		}
		positioned = false;
	}

	internal static void Reset()
	{
		if (Object.op_Implicit((Object)(object)topic) && hidden)
		{
			topic.SetActive(originalActive);
		}
		RestorePosition();
		display = (topic = null);
		panel = null;
		canvas = null;
		hidden = false;
	}
}
[HarmonyPatch(typeof(UITooltip), "UpdateTextElements")]
internal static class FilterTooltipLayoutPatch
{
	private static void Prefix(UITooltip __instance, GameObject ___m_tooltip)
	{
		FilterTooltips.Refresh(__instance, ___m_tooltip);
	}
}
[HarmonyPatch(typeof(UITooltip), "LateUpdate")]
internal static class FilterTooltipCursorPatch
{
	private static void Postfix(UITooltip __instance, UITooltip ___m_current, GameObject ___m_tooltip)
	{
		if (!((Object)(object)__instance != (Object)(object)___m_current))
		{
			if (ZInput.IsMouseActive())
			{
				FilterTooltips.FollowCursor(__instance, ___m_tooltip);
			}
			else
			{
				FilterTooltips.RestorePosition();
			}
		}
	}
}
internal static class HeaderFilterButton
{
	private static TMP_Text trackedName;

	private static Button trackedButton;

	private static UITooltip trackedTooltip;

	private static string tooltipText;

	private static Vector3 titleEdge;

	private static bool boundsReady;

	private static bool subscribed;

	internal static Button Create(InventoryGui gui, Button source, Color iconColor, UnityAction action)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Expected O, but got Unknown
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Expected O, but got Unknown
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Expected O, but got Unknown
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		Reset();
		GameObject val = Object.Instantiate<GameObject>(((Component)source).gameObject, (Transform)(object)gui.m_container, false);
		((Object)val).name = "ItemFilter";
		val.SetActive(false);
		Button component = val.GetComponent<Button>();
		component.onClick = new ButtonClickedEvent();
		((UnityEvent)component.onClick).AddListener(action);
		((Selectable)component).interactable = true;
		Navigation navigation = default(Navigation);
		((Navigation)(ref navigation)).mode = (Mode)3;
		((Selectable)component).navigation = navigation;
		TMP_Text[] componentsInChildren = val.GetComponentsInChildren<TMP_Text>(true);
		foreach (TMP_Text val2 in componentsInChildren)
		{
			((Component)val2).gameObject.SetActive(false);
		}
		float headerButtonSize = UiTheme.Current.headerButtonSize;
		RectTransform val3 = (RectTransform)val.transform;
		Vector2 val4 = default(Vector2);
		((Vector2)(ref val4))..ctor(0.5f, 0.5f);
		val3.anchorMax = val4;
		val3.anchorMin = val4;
		val3.pivot = new Vector2(0f, 0.5f);
		((Transform)val3).localScale = Vector3.one;
		val3.sizeDelta = Vector2.one * headerButtonSize;
		LayoutElement val5 = val.GetComponent<LayoutElement>() ?? val.AddComponent<LayoutElement>();
		val5.ignoreLayout = true;
		float num = (val5.preferredHeight = headerButtonSize);
		float num3 = (val5.minHeight = num);
		float minWidth = (val5.preferredWidth = num3);
		val5.minWidth = minWidth;
		GameObject val6 = new GameObject("FilterIcon", new Type[2]
		{
			typeof(RectTransform),
			typeof(FilterIconGraphic)
		});
		RectTransform val7 = (RectTransform)val6.transform;
		((Transform)val7).SetParent((Transform)(object)val3, false);
		Vector2 val8 = default(Vector2);
		((Vector2)(ref val8))..ctor(0.5f, 0.5f);
		val7.pivot = val8;
		val4 = (val7.anchorMin = (val7.anchorMax = val8));
		val7.sizeDelta = Vector2.one * UiTheme.Current.headerIconSize;
		FilterIconGraphic component2 = val6.GetComponent<FilterIconGraphic>();
		((Graphic)component2).color = iconColor;
		((Graphic)component2).raycastTarget = false;
		UITooltip val11 = val.GetComponent<UITooltip>() ?? val.AddComponent<UITooltip>();
		if (!Object.op_Implicit((Object)(object)val11.m_tooltipPrefab))
		{
			UITooltip val12 = ((IEnumerable<UITooltip>)((Component)gui).GetComponentsInChildren<UITooltip>(true)).FirstOrDefault((Func<UITooltip, bool>)((UITooltip t) => Object.op_Implicit((Object)(object)t.m_tooltipPrefab)));
			if (Object.op_Implicit((Object)(object)val12))
			{
				val11.m_tooltipPrefab = val12.m_tooltipPrefab;
			}
		}
		val11.m_gamepadFocusObject = val;
		trackedButton = component;
		trackedTooltip = val11;
		RefreshTooltip();
		return component;
	}

	internal static bool FollowName(Button button, TMP_Text name)
	{
		if (!Object.op_Implicit((Object)(object)name) || !((Behaviour)name).isActiveAndEnabled || string.IsNullOrWhiteSpace(name.text))
		{
			return false;
		}
		if ((Object)(object)trackedName != (Object)(object)name)
		{
			trackedName = name;
			boundsReady = false;
			if (!subscribed)
			{
				TMPro_EventManager.TEXT_CHANGED_EVENT.Add((Action<Object>)OnTextChanged);
				subscribed = true;
			}
			if (!name.havePropertiesChanged)
			{
				CaptureBounds();
			}
		}
		trackedButton = button;
		if (!boundsReady)
		{
			return false;
		}
		ApplyPosition();
		RefreshTooltip();
		return true;
	}

	private static void OnTextChanged(Object changed)
	{
		if ((object)changed == trackedName)
		{
			CaptureBounds();
		}
	}

	private static void CaptureBounds()
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: 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_0078: 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)
		if (Object.op_Implicit((Object)(object)trackedName) && trackedName.textInfo != null)
		{
			Bounds textBounds = trackedName.textBounds;
			boundsReady = trackedName.textInfo.characterCount > 0 && ((Bounds)(ref textBounds)).size.x > 0f;
			titleEdge = new Vector3(((Bounds)(ref textBounds)).max.x, ((Bounds)(ref textBounds)).center.y, 0f);
		}
	}

	private static void ApplyPosition()
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = (RectTransform)((Component)trackedButton).transform;
		Vector3 val2 = trackedName.transform.TransformPoint(titleEdge);
		Vector3 val3 = ((Transform)val).parent.InverseTransformPoint(val2);
		val3.x += UiTheme.Current.headerButtonGap;
		if (((Transform)val).localPosition != val3)
		{
			((Transform)val).localPosition = val3;
		}
	}

	private static void RefreshTooltip()
	{
		string text = Texts.Get("filter");
		if (Object.op_Implicit((Object)(object)trackedTooltip) && !(text == tooltipText))
		{
			FilterTooltips.SetHeader(trackedTooltip, text);
			tooltipText = text;
		}
	}

	internal static void Reset()
	{
		if (subscribed)
		{
			TMPro_EventManager.TEXT_CHANGED_EVENT.Remove((Action<Object>)OnTextChanged);
		}
		subscribed = false;
		trackedName = null;
		trackedButton = null;
		trackedTooltip = null;
		tooltipText = null;
		boundsReady = false;
	}
}
internal sealed class FilterIconGraphic : MaskableGraphic
{
	internal static readonly Vector2[] Outline = (Vector2[])(object)new Vector2[6]
	{
		new Vector2(22f, 3f),
		new Vector2(2f, 3f),
		new Vector2(10f, 12.46f),
		new Vector2(10f, 19f),
		new Vector2(14f, 21f),
		new Vector2(14f, 12.46f)
	};

	protected override void OnPopulateMesh(VertexHelper mesh)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: 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_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: 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_0088: 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_008f: 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_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: 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_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		mesh.Clear();
		Rect rect = ((Graphic)this).rectTransform.rect;
		float scale = Mathf.Min(((Rect)(ref rect)).width, ((Rect)(ref rect)).height) / 24f;
		float num = UiTheme.Current.headerIconStroke * 0.5f;
		UIVertex[] array = (UIVertex[])(object)new UIVertex[4];
		for (int i = 0; i < Outline.Length; i++)
		{
			Vector2 val = Point(Outline[i], ((Rect)(ref rect)).center, scale);
			Vector2 val2 = Point(Outline[(i + 1) % Outline.Length], ((Rect)(ref rect)).center, scale);
			Vector2 val3 = val2 - val;
			Vector2 normalized = ((Vector2)(ref val3)).normalized;
			Vector2 val4 = new Vector2(0f - normalized.y, normalized.x) * num;
			for (int j = 0; j < array.Length; j++)
			{
				array[j] = UIVertex.simpleVert;
				array[j].color = Color32.op_Implicit(((Graphic)this).color);
			}
			array[0].position = Vector2.op_Implicit(val - val4);
			array[1].position = Vector2.op_Implicit(val + val4);
			array[2].position = Vector2.op_Implicit(val2 + val4);
			array[3].position = Vector2.op_Implicit(val2 - val4);
			mesh.AddUIVertexQuad(array);
		}
	}

	private static Vector2 Point(Vector2 point, Vector2 center, float scale)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		return center + new Vector2(point.x - 12f, 12f - point.y) * scale;
	}
}
internal sealed class CatalogItem
{
	internal string Id;

	internal string Name;

	internal string Category;

	internal Sprite Icon;
}
internal static class ItemCatalog
{
	internal static bool IsInventoryItem(string id)
	{
		GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(id) : null);
		SharedData val2 = ((!Object.op_Implicit((Object)(object)val)) ? null : val.GetComponent<ItemDrop>()?.m_itemData?.m_shared);
		return val2 != null && CatalogRules.Visible(discovered: true, showUndiscovered: false, hasIcon: true, ((object)Unsafe.As<ItemType, ItemType>(ref val2.m_itemType)/*cast due to .constrained prefix*/).ToString(), val2.m_maxStackSize, val2.m_name);
	}

	internal static List<CatalogItem> Build(Player player)
	{
		List<CatalogItem> list = new List<CatalogItem>();
		HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
		if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || !Object.op_Implicit((Object)(object)player))
		{
			return list;
		}
		foreach (GameObject item in ObjectDB.instance.m_items.OrderBy<GameObject, string>((GameObject p) => Object.op_Implicit((Object)(object)p) ? ((Object)p).name : "", StringComparer.Ordinal))
		{
			if (!Object.op_Implicit((Object)(object)item) || !hashSet.Add(((Object)item).name) || !StorageFilter.ValidId(((Object)item).name))
			{
				continue;
			}
			SharedData val = item.GetComponent<ItemDrop>()?.m_itemData?.m_shared;
			if (val != null)
			{
				Sprite val2 = val.m_icons?.FirstOrDefault((Func<Sprite, bool>)((Sprite sprite) => Object.op_Implicit((Object)(object)sprite)));
				if (CatalogRules.Visible(player.IsKnownMaterial(val.m_name), Plugin.ShowUndiscoveredItems.Value, Object.op_Implicit((Object)(object)val2), ((object)Unsafe.As<ItemType, ItemType>(ref val.m_itemType)/*cast due to .constrained prefix*/).ToString(), val.m_maxStackSize, val.m_name))
				{
					list.Add(new CatalogItem
					{
						Id = ((Object)item).name,
						Name = Localization.instance.Localize(val.m_name),
						Category = CatalogRules.Category(((object)Unsafe.As<ItemType, ItemType>(ref val.m_itemType)/*cast due to .constrained prefix*/).ToString()),
						Icon = val2
					});
				}
			}
		}
		return list.OrderBy<CatalogItem, string>((CatalogItem item) => item.Name, StringComparer.Ordinal).ThenBy<CatalogItem, string>((CatalogItem item) => item.Id, StringComparer.Ordinal).ToList();
	}

	internal static string DisplayName(string id)
	{
		GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(id) : null);
		SharedData val2 = ((!Object.op_Implicit((Object)(object)val)) ? null : val.GetComponent<ItemDrop>()?.m_itemData?.m_shared);
		return (val2 == null) ? (Texts.Get("missing") + ": " + id) : Localization.instance.Localize(val2.m_name);
	}

	internal static CatalogItem Resolve(string id)
	{
		GameObject val = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(id) : null);
		SharedData val2 = ((!Object.op_Implicit((Object)(object)val)) ? null : val.GetComponent<ItemDrop>()?.m_itemData?.m_shared);
		return new CatalogItem
		{
			Id = id,
			Name = DisplayName(id),
			Category = ((val2 == null) ? "other" : CatalogRules.Category(((object)Unsafe.As<ItemType, ItemType>(ref val2.m_itemType)/*cast due to .constrained prefix*/).ToString())),
			Icon = val2?.m_icons?.FirstOrDefault((Func<Sprite, bool>)((Sprite sprite) => Object.op_Implicit((Object)(object)sprite)))
		};
	}
}
internal sealed class PickerControls
{
	internal readonly Button Template;

	internal readonly TMP_Text Font;

	internal readonly UITooltip TooltipStyle;

	internal readonly Scrollbar ScrollbarStyle;

	private UiTheme T => UiTheme.Current;

	internal PickerControls(Button template, TMP_Text font, UITooltip tooltipStyle, Scrollbar scrollbarStyle)
	{
		Template = template;
		Font = font;
		TooltipStyle = tooltipStyle;
		ScrollbarStyle = scrollbarStyle;
	}

	internal static RectTransform Node(string name, Transform parent)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
		val.transform.SetParent(parent, false);
		return (RectTransform)val.transform;
	}

	internal static void Stretch(RectTransform rect, float inset = 0f)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: 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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		rect.anchorMin = Vector2.zero;
		rect.anchorMax = Vector2.one;
		rect.offsetMin = Vector2.one * inset;
		rect.offsetMax = -Vector2.one * inset;
	}

	internal static LayoutElement Size(GameObject obj, float height, float width = -1f)
	{
		LayoutElement val = obj.GetComponent<LayoutElement>() ?? obj.AddComponent<LayoutElement>();
		float minHeight = (val.preferredHeight = height);
		val.minHeight = minHeight;
		if (width >= 0f)
		{
			minHeight = (val.preferredWidth = width);
			val.minWidth = minHeight;
		}
		return val;
	}

	internal Image Background(GameObject obj, Image source = null)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		Image val = obj.AddComponent<Image>();
		source = (Object.op_Implicit((Object)(object)source) ? source : ((Component)Template).GetComponent<Image>());
		if (Object.op_Implicit((Object)(object)source))
		{
			val.sprite = source.sprite;
			val.type = source.type;
			((Graphic)val).color = ((Graphic)source).color;
			((Graphic)val).material = ((Graphic)source).material;
		}
		return val;
	}

	internal TMP_Text Text(Transform parent, string name, string text, float size, float height = -1f)
	{
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Node(name, parent);
		((Component)val).gameObject.SetActive(false);
		TextMeshProUGUI val2 = ((Component)val).gameObject.AddComponent<TextMeshProUGUI>();
		((TMP_Text)val2).font = Font.font;
		((TMP_Text)val2).fontSharedMaterial = Font.fontSharedMaterial;
		((Graphic)val2).color = ((Graphic)Font).color;
		((TMP_Text)val2).fontSize = size;
		((TMP_Text)val2).text = text;
		((Graphic)val2).raycastTarget = false;
		((TMP_Text)val2).richText = false;
		((TMP_Text)val2).alignment = (TextAlignmentOptions)4097;
		((TMP_Text)val2).overflowMode = (TextOverflowModes)1;
		if (height >= 0f)
		{
			Size(((Component)val).gameObject, height);
		}
		((Component)val).gameObject.SetActive(true);
		return (TMP_Text)(object)val2;
	}

	internal Button Button(Transform parent, string name, string label, UnityAction action)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Expected O, but got Unknown
		//IL_009c: 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)
		GameObject val = Object.Instantiate<GameObject>(((Component)Template).gameObject, parent, false);
		((Object)val).name = name;
		Button component = val.GetComponent<Button>();
		component.onClick = new ButtonClickedEvent();
		((UnityEvent)component.onClick).AddListener(action);
		((Selectable)component).interactable = true;
		TMP_Text[] componentsInChildren = val.GetComponentsInChildren<TMP_Text>(true);
		foreach (TMP_Text val2 in componentsInChildren)
		{
			val2.text = label;
			val2.fontSize = T.bodySize;
		}
		Size(val, T.controlHeight);
		((RectTransform)val.transform).sizeDelta = new Vector2(T.buttonWidth, T.controlHeight);
		val.SetActive(true);
		return component;
	}

	internal UITooltip Tooltip(GameObject obj, string text)
	{
		UITooltip val = obj.GetComponent<UITooltip>() ?? obj.AddComponent<UITooltip>();
		if (Object.op_Implicit((Object)(object)TooltipStyle))
		{
			val.m_tooltipPrefab = TooltipStyle.m_tooltipPrefab;
		}
		val.m_gamepadFocusObject = obj;
		FilterTooltips.Set(val, text);
		return val;
	}

	internal ColorBlock ListColors()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
		ColorBlock colors = ((Selectable)Template).colors;
		((ColorBlock)(ref colors)).normalColor = new Color(1f, 1f, 1f, T.rowOpacity);
		((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 1f, 1f, T.rowHoverOpacity);
		((ColorBlock)(ref colors)).selectedColor = new Color(1f, 1f, 1f, T.rowSelectedOpacity);
		((ColorBlock)(ref colors)).pressedColor = new Color(1f, 1f, 1f, T.rowPressedOpacity);
		((ColorBlock)(ref colors)).disabledColor = new Color(1f, 1f, 1f, T.rowDisabledOpacity);
		return colors;
	}

	internal Toggle Checkbox(Transform parent, string key, Action<bool> changed)
	{
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: 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_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Expected O, but got Unknown
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: 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_0236: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Node("Category_" + key, parent);
		Image val2 = Background(((Component)val).gameObject);
		val2.sprite = null;
		((Graphic)val2).color = new Color(T.checkboxShade, T.checkboxShade, T.checkboxShade, T.checkboxOpacity);
		Toggle val3 = ((Component)val).gameObject.AddComponent<Toggle>();
		((Selectable)val3).targetGraphic = (Graphic)(object)val2;
		((Selectable)val3).colors = ((Selectable)Template).colors;
		val3.toggleTransition = (ToggleTransition)0;
		RectTransform val4 = Node("Box", (Transform)(object)val);
		Vector2 val5 = default(Vector2);
		((Vector2)(ref val5))..ctor(0f, 0.5f);
		val4.anchorMax = val5;
		val4.anchorMin = val5;
		val4.pivot = new Vector2(0f, 0.5f);
		val4.anchoredPosition = new Vector2(T.gap, 0f);
		val4.sizeDelta = Vector2.one * T.categoryCheckSize;
		PickerGlyph pickerGlyph = ((Component)val4).gameObject.AddComponent<PickerGlyph>();
		pickerGlyph.Kind = PickerGlyphKind.Box;
		((Graphic)pickerGlyph).color = ((Graphic)Font).color;
		((Graphic)pickerGlyph).raycastTarget = false;
		RectTransform val6 = Node("Check", (Transform)(object)val4);
		Stretch(val6);
		PickerGlyph pickerGlyph2 = ((Component)val6).gameObject.AddComponent<PickerGlyph>();
		pickerGlyph2.Kind = PickerGlyphKind.Check;
		((Graphic)pickerGlyph2).color = ((Graphic)Font).color;
		((Graphic)pickerGlyph2).raycastTarget = false;
		val3.graphic = (Graphic)(object)pickerGlyph2;
		TMP_Text val7 = Text((Transform)(object)val, "Label", Texts.Get(key), T.bodySize);
		Stretch((RectTransform)val7.transform);
		((RectTransform)val7.transform).offsetMin = new Vector2(T.categoryCheckSize + T.gap * 2f, 0f);
		((RectTransform)val7.transform).offsetMax = new Vector2(0f - T.gap, 0f);
		((UnityEvent<bool>)(object)val3.onValueChanged).AddListener((UnityAction<bool>)delegate(bool value)
		{
			changed(value);
		});
		return val3;
	}

	internal Button Arrow(Transform parent, string name, PickerGlyphKind kind, string tooltip, UnityAction action, float size = -1f)
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		Button val = Button(parent, name, "", action);
		float num = ((size > 0f) ? size : T.transferButtonSize);
		Size(((Component)val).gameObject, num, num);
		RectTransform val2 = (RectTransform)((Component)val).transform;
		val2.sizeDelta = Vector2.one * num;
		TMP_Text[] componentsInChildren = ((Component)val).GetComponentsInChildren<TMP_Text>(true);
		foreach (TMP_Text val3 in componentsInChildren)
		{
			((Component)val3).gameObject.SetActive(false);
		}
		RectTransform val4 = Node("Icon", (Transform)(object)val2);
		Vector2 val5 = default(Vector2);
		((Vector2)(ref val5))..ctor(0.5f, 0.5f);
		val4.pivot = val5;
		Vector2 anchorMin = (val4.anchorMax = val5);
		val4.anchorMin = anchorMin;
		val4.sizeDelta = Vector2.one * ((size > 0f) ? (num * T.scrollArrowIconRatio) : T.listIconSize);
		PickerGlyph pickerGlyph = ((Component)val4).gameObject.AddComponent<PickerGlyph>();
		pickerGlyph.Kind = kind;
		((Graphic)pickerGlyph).color = ((Graphic)Font).color;
		((Graphic)pickerGlyph).raycastTarget = false;
		Tooltip(((Component)val).gameObject, tooltip);
		return val;
	}
}
internal enum PickerGlyphKind
{
	Box,
	Check,
	Right,
	Left,
	Up,
	Down
}
internal sealed class PickerGlyph : MaskableGraphic
{
	internal PickerGlyphKind Kind;

	protected override void OnPopulateMesh(VertexHelper mesh)
	{
		mesh.Clear();
		if (Kind == PickerGlyphKind.Box)
		{
			Line(mesh, 3f, 3f, 21f, 3f);
			Line(mesh, 21f, 3f, 21f, 21f);
			Line(mesh, 21f, 21f, 3f, 21f);
			Line(mesh, 3f, 21f, 3f, 3f);
			return;
		}
		if (Kind == PickerGlyphKind.Check)
		{
			Line(mesh, 20f, 6f, 9f, 17f);
			Line(mesh, 9f, 17f, 4f, 12f);
			return;
		}
		bool flag = Kind == PickerGlyphKind.Up || Kind == PickerGlyphKind.Down;
		float num = ((Kind == PickerGlyphKind.Right || Kind == PickerGlyphKind.Down) ? 1f : (-1f));
		if (flag)
		{
			Line(mesh, 12f, 12f - 8f * num, 12f, 12f + 8f * num);
			Line(mesh, 5f, 12f + num * 2f, 12f, 12f + num * 9f);
			Line(mesh, 12f, 12f + num * 9f, 19f, 12f + num * 2f);
		}
		else
		{
			Line(mesh, 12f - 8f * num, 12f, 12f + 8f * num, 12f);
			Line(mesh, 12f + num * 2f, 5f, 12f + num * 9f, 12f);
			Line(mesh, 12f + num * 9f, 12f, 12f + num * 2f, 19f);
		}
	}

	private void Line(VertexHelper mesh, float x1, float y1, float x2, float y2)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: 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_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		Rect rect = ((Graphic)this).rectTransform.rect;
		float num = Mathf.Min(((Rect)(ref rect)).width, ((Rect)(ref rect)).height) / 24f;
		Vector2 val = ((Rect)(ref rect)).center + new Vector2(x1 - 12f, 12f - y1) * num;
		Vector2 val2 = ((Rect)(ref rect)).center + new Vector2(x2 - 12f, 12f - y2) * num;
		Vector2 val3 = val2 - val;
		Vector2 normalized = ((Vector2)(ref val3)).normalized;
		Vector2 val4 = new Vector2(0f - normalized.y, normalized.x) * UiTheme.Current.headerIconStroke * 0.5f;
		int currentVertCount = mesh.currentVertCount;
		mesh.AddVert(Vector2.op_Implicit(val - val4), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		mesh.AddVert(Vector2.op_Implicit(val + val4), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		mesh.AddVert(Vector2.op_Implicit(val2 + val4), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		mesh.AddVert(Vector2.op_Implicit(val2 - val4), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
		mesh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2);
		mesh.AddTriangle(currentVertCount, currentVertCount + 2, currentVertCount + 3);
	}
}
internal sealed class PickerListView
{
	private sealed class Row
	{
		internal PickerRowButton Button;

		internal Image Icon;

		internal TMP_Text Label;

		internal Outline Selection;

		internal UITooltip Tooltip;

		internal CatalogItem Item;
	}

	private readonly PickerControls ui;

	private readonly List<Row> rows = new List<Row>();

	private readonly Action<string> selected;

	private readonly Action<string> activated;

	private readonly Action changed;

	private IReadOnlyList<CatalogItem> items = Array.Empty<CatalogItem>();

	private readonly RectTransform content;

	private readonly RectTransform viewport;

	private readonly ScrollRect scroll;

	private readonly Scrollbar scrollbar;

	private readonly Button scrollUp;

	private readonly Button scrollDown;

	private readonly TMP_Text empty;

	private string selectedId;

	private bool interactable = true;

	private bool refreshing;

	private bool refreshPending;

	internal readonly RectTransform Column;

	internal readonly TMP_Text Heading;

	private UiTheme T => UiTheme.Current;

	internal Selectable FocusTarget
	{
		get
		{
			foreach (Row row in rows)
			{
				if (((Component)row.Button).gameObject.activeInHierarchy && row.Item?.Id == selectedId)
				{
					return (Selectable)(object)row.Button;
				}
			}
			foreach (Row row2 in rows)
			{
				if (((Component)row2.Button).gameObject.activeInHierarchy)
				{
					return (Selectable)(object)row2.Button;
				}
			}
			return null;
		}
	}

	internal PickerListView(PickerControls ui, Transform parent, string name, string heading, string emptyText, Action<string> selected, Action changed, Action<string> activated = null)
	{
		//IL_0186: 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_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_0275: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		//IL_0314: Unknown result type (might be due to invalid IL or missing references)
		//IL_0331: Unknown result type (might be due to invalid IL or missing references)
		//IL_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_036c: Expected O, but got Unknown
		//IL_037c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0383: Expected O, but got Unknown
		//IL_0398: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fc: Expected O, but got Unknown
		//IL_040c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0413: Expected O, but got Unknown
		//IL_0428: Unknown result type (might be due to invalid IL or missing references)
		//IL_0430: Unknown result type (might be due to invalid IL or missing references)
		//IL_0444: Unknown result type (might be due to invalid IL or missing references)
		//IL_0451: Unknown result type (might be due to invalid IL or missing references)
		//IL_0495: Unknown result type (might be due to invalid IL or missing references)
		//IL_04bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_04de: 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_04f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0502: Unknown result type (might be due to invalid IL or missing references)
		//IL_0518: Unknown result type (might be due to invalid IL or missing references)
		//IL_0587: Unknown result type (might be due to invalid IL or missing references)
		//IL_0597: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_05fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_065a: Unknown result type (might be due to invalid IL or missing references)
		//IL_066f: Expected O, but got Unknown
		this.ui = ui;
		this.selected = selected;
		this.changed = changed;
		this.activated = activated;
		Column = PickerControls.Node(name, parent);
		LayoutElement val = ((Component)Column).gameObject.AddComponent<LayoutElement>();
		val.minWidth = 0f;
		val.flexibleWidth = 1f;
		VerticalLayoutGroup val2 = ((Component)Column).gameObject.AddComponent<VerticalLayoutGroup>();
		((HorizontalOrVerticalLayoutGroup)val2).spacing = T.gap;
		((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = (((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = true);
		((HorizontalOrVerticalLayoutGroup)val2).childForceExpandWidth = true;
		((HorizontalOrVerticalLayoutGroup)val2).childForceExpandHeight = false;
		Heading = ui.Text((Transform)(object)Column, "Heading", heading, T.bodySize, T.listHeaderHeight);
		RectTransform val3 = PickerControls.Node("ScrollView", (Transform)(object)Column);
		LayoutElement val4 = PickerControls.Size(((Component)val3).gameObject, T.listRowHeight * 2f);
		val4.flexibleHeight = 1f;
		scroll = ((Component)val3).gameObject.AddComponent<ScrollRect>();
		Image val5 = ui.Background(((Component)val3).gameObject);
		val5.sprite = null;
		((Graphic)val5).color = new Color(T.listSurfaceShade, T.listSurfaceShade, T.listSurfaceShade, T.listSurfaceOpacity);
		scroll.horizontal = false;
		scroll.inertia = false;
		scroll.scrollSensitivity = T.scrollSensitivity;
		scroll.movementType = (MovementType)2;
		viewport = PickerControls.Node("Viewport", (Transform)(object)val3);
		PickerControls.Stretch(viewport);
		viewport.offsetMax = new Vector2(0f - T.scrollbarWidth - T.scrollbarGap, 0f);
		Image val6 = ((Component)viewport).gameObject.AddComponent<Image>();
		((Graphic)val6).color = Color.clear;
		((Component)viewport).gameObject.AddComponent<RectMask2D>();
		content = PickerControls.Node("Content", (Transform)(object)viewport);
		content.anchorMin = new Vector2(0f, 1f);
		content.anchorMax = Vector2.one;
		content.pivot = new Vector2(0.5f, 1f);
		content.sizeDelta = Vector2.zero;
		scroll.content = content;
		scroll.viewport = viewport;
		RectTransform val7 = PickerControls.Node("Scrollbar", (Transform)(object)val3);
		val7.anchorMin = new Vector2(1f, 0f);
		val7.anchorMax = Vector2.one;
		val7.pivot = Vector2.one;
		val7.sizeDelta = new Vector2(T.scrollbarWidth, 0f);
		scrollUp = ui.Arrow((Transform)(object)val7, "ScrollUp", PickerGlyphKind.Up, Texts.Get("scrollup"), (UnityAction)delegate
		{
			StepScroll(-1);
		}, T.scrollbarWidth);
		RectTransform val8 = (RectTransform)((Component)scrollUp).transform;
		Vector2 val9 = default(Vector2);
		((Vector2)(ref val9))..ctor(0.5f, 1f);
		val8.anchorMax = val9;
		val8.anchorMin = val9;
		val8.pivot = new Vector2(0.5f, 1f);
		val8.anchoredPosition = Vector2.zero;
		scrollDown = ui.Arrow((Transform)(object)val7, "ScrollDown", PickerGlyphKind.Down, Texts.Get("scrolldown"), (UnityAction)delegate
		{
			StepScroll(1);
		}, T.scrollbarWidth);
		RectTransform val10 = (RectTransform)((Component)scrollDown).transform;
		((Vector2)(ref val9))..ctor(0.5f, 0f);
		val10.anchorMax = val9;
		val10.anchorMin = val9;
		val10.pivot = new Vector2(0.5f, 0f);
		val10.anchoredPosition = Vector2.zero;
		RectTransform val11 = PickerControls.Node("Track", (Transform)(object)val7);
		PickerControls.Stretch(val11);
		val11.offsetMin = new Vector2(0f, T.scrollbarWidth + T.scrollbarGap);
		val11.offsetMax = new Vector2(0f, 0f - T.scrollbarWidth - T.scrollbarGap);
		Image val12 = ui.Background(((Component)val11).gameObject);
		((Graphic)val12).color = new Color(((Graphic)val12).color.r, ((Graphic)val12).color.g, ((Graphic)val12).color.b, ((Graphic)val12).color.a * T.scrollTrackOpacity);
		scrollbar = ((Component)val11).gameObject.AddComponent<Scrollbar>();
		RectTransform val13 = PickerControls.Node("Handle", (Transform)(object)val11);
		PickerControls.Stretch(val13);
		Image val14 = ui.Background(((Component)val13).gameObject, (Image)(Object.op_Implicit((Object)(object)ui.ScrollbarStyle) ? /*isinst with value type is only supported in some contexts*/: null));
		((Graphic)val14).color = new Color(((Graphic)ui.Font).color.r, ((Graphic)ui.Font).color.g, ((Graphic)ui.Font).color.b, T.scrollHandleOpacity);
		scrollbar.handleRect = val13;
		((Selectable)scrollbar).targetGraphic = (Graphic)(object)val14;
		scrollbar.direction = (Direction)2;
		((Selectable)scrollbar).colors = ((Selectable)ui.Template).colors;
		scroll.verticalScrollbar = scrollbar;
		scroll.verticalScrollbarVisibility = (ScrollbarVisibility)0;
		empty = ui.Text((Transform)(object)viewport, "Empty", emptyText, T.bodySize);
		PickerControls.Stretch((RectTransform)empty.transform, T.gap);
		empty.alignment = (TextAlignmentOptions)257;
		empty.overflowMode = (TextOverflowModes)0;
		((UnityEvent<Vector2>)(object)scroll.onValueChanged).AddListener((UnityAction<Vector2>)delegate
		{
			RefreshVisible();
		});
		((Component)viewport).gameObject.AddComponent<PickerViewportWatcher>().Owner = this;
	}

	internal void SetItems(IReadOnlyList<CatalogItem> values, string selection, bool resetScroll)
	{
		//IL_0032: 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)
		items = values;
		selectedId = selection;
		content.sizeDelta = new Vector2(0f, (float)items.Count * T.listRowHeight);
		if (resetScroll)
		{
			content.anchoredPosition = Vector2.zero;
		}
		((Component)empty).gameObject.SetActive(items.Count == 0);
		RefreshVisible();
	}

	internal void SetSelection(string id)
	{
		selectedId = id;
		foreach (Row row in rows)
		{
			((Behaviour)row.Selection).enabled = row.Item != null && row.Item.Id == id;
		}
	}

	internal void SetInteractable(bool enabled)
	{
		interactable = enabled;
		foreach (Row row in rows)
		{
			((Selectable)row.Button).interactable = enabled;
		}
		UpdateScrollButtons();
	}

	internal void RefreshVisible()
	{
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Expected O, but got Unknown
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		if (refreshing || !Object.op_Implicit((Object)(object)viewport))
		{
			return;
		}
		if (CanvasUpdateRegistry.IsRebuildingLayout() || CanvasUpdateRegistry.IsRebuildingGraphics())
		{
			refreshPending = true;
			return;
		}
		refreshPending = false;
		refreshing = true;
		try
		{
			int count = items.Count;
			float listRowHeight = T.listRowHeight;
			float y = content.anchoredPosition.y;
			Rect rect = viewport.rect;
			float viewportHeight;
			if (!(((Rect)(ref rect)).height > 0f))
			{
				viewportHeight = T.panelHeight;
			}
			else
			{
				rect = viewport.rect;
				viewportHeight = ((Rect)(ref rect)).height;
			}
			VisibleRows visibleRows = VisibleRows.Calculate(count, listRowHeight, y, viewportHeight, T.listOverscan);
			while (rows.Count < visibleRows.Count)
			{
				rows.Add(CreateRow());
			}
			Vector2 val2 = default(Vector2);
			for (int i = 0; i < rows.Count; i++)
			{
				Row row = rows[i];
				if (i >= visibleRows.Count)
				{
					if (((Component)row.Button).gameObject.activeSelf)
					{
						((Component)row.Button).gameObject.SetActive(false);
					}
					continue;
				}
				int num = visibleRows.First + i;
				if (row.Button.Index != num && Object.op_Implicit((Object)(object)EventSystem.current) && (Object)(object)EventSystem.current.currentSelectedGameObject == (Object)(object)((Component)row.Button).gameObject)
				{
					EventSystem.current.SetSelectedGameObject((GameObject)null);
				}
				row.Button.Index = num;
				RectTransform val = (RectTransform)((Component)row.Button).transform;
				((Vector2)(ref val2))..ctor(0f, (float)(-num) * T.listRowHeight);
				if (val.anchoredPosition != val2)
				{
					val.anchoredPosition = val2;
				}
				CatalogItem catalogItem = items[num];
				row.Button.ItemId = catalogItem.Id;
				if (row.Item != catalogItem)
				{
					row.Item = catalogItem;
					row.Label.text = catalogItem.Name;
					row.Icon.sprite = catalogItem.Icon;
					((Component)row.Icon).gameObject.SetActive(Object.op_Implicit((Object)(object)catalogItem.Icon));
					FilterTooltips.Set(row.Tooltip, catalogItem.Name);
				}
				((Behaviour)row.Selection).enabled = catalogItem.Id == selectedId;
				((Selectable)row.Button).interactable = interactable;
				if (!((Component)row.Button).gameObject.activeSelf)
				{
					((Component)row.Button).gameObject.SetActive(true);
				}
			}
			UpdateScrollButtons();
			changed();
		}
		finally
		{
			refreshing = false;
		}
	}

	internal void FlushPendingRefresh()
	{
		if (refreshPending)
		{
			RefreshVisible();
		}
	}

	private void StepScroll(int direction)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		if (interactable)
		{
			int count = items.Count;
			float listRowHeight = T.listRowHeight;
			Rect rect = viewport.rect;
			float num = ScrollPosition.Step(count, listRowHeight, ((Rect)(ref rect)).height, content.anchoredPosition.y, direction);
			content.anchoredPosition = new Vector2(0f, num);
			RefreshVisible();
		}
	}

	private void UpdateScrollButtons()
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: 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_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		float num = (float)items.Count * T.listRowHeight;
		Rect rect = viewport.rect;
		float num2 = Mathf.Max(0f, num - ((Rect)(ref rect)).height);
		rect = ((RectTransform)((Component)scrollbar).transform).rect;
		float height = ((Rect)(ref rect)).height;
		rect = viewport.rect;
		float num3 = Mathf.Clamp01(((Rect)(ref rect)).height / Mathf.Max(1f, (float)items.Count * T.listRowHeight));
		float num4 = Mathf.Clamp01(T.scrollbarWidth / Mathf.Max(T.scrollbarWidth, height));
		scrollbar.size = Mathf.Max(num3, num4);
		((Selectable)scrollUp).interactable = interactable && content.anchoredPosition.y > 0f;
		((Selectable)scrollDown).interactable = interactable && content.anchoredPosition.y < num2;
		((Selectable)scrollbar).interactable = interactable && num2 > 0f;
	}

	private Row CreateRow()
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: 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_0108: Expected O, but got Unknown
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Expected O, but got Unknown
		//IL_026b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0289: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = PickerControls.Node("ItemRow", (Transform)(object)content);
		((Component)val).gameObject.SetActive(false);
		val.anchorMin = new Vector2(0f, 1f);
		val.anchorMax = Vector2.one;
		val.pivot = new Vector2(0.5f, 1f);
		val.sizeDelta = new Vector2(0f, T.listRowHeight - T.listRowGap);
		Image targetGraphic = ui.Background(((Component)val).gameObject);
		PickerRowButton button = ((Component)val).gameObject.AddComponent<PickerRowButton>();
		button.Owner = this;
		button.Index = -1;
		((Selectable)button).targetGraphic = (Graphic)(object)targetGraphic;
		((Selectable)button).colors = ui.ListColors();
		((UnityEvent)((Button)button).onClick).AddListener((UnityAction)delegate
		{
			SelectIndex(button.Index);
		});
		Outline val2 = ((Component)val).gameObject.AddComponent<Outline>();
		((Shadow)val2).effectColor = ((Graphic)ui.Font).color;
		((Shadow)val2).effectDistance = Vector2.one * T.selectionOutline;
		((Shadow)val2).useGraphicAlpha = false;
		((Behaviour)val2).enabled = false;
		RectTransform val3 = PickerControls.Node("Icon", (Transform)(object)val);
		Vector2 val4 = default(Vector2);
		((Vector2)(ref val4))..ctor(0f, 0.5f);
		val3.anchorMax = val4;
		val3.anchorMin = val4;
		val3.pivot = new Vector2(0f, 0.5f);
		val3.anchoredPosition = new Vector2(T.listRowPadding, 0f);
		val3.sizeDelta = Vector2.one * T.listIconSize;
		Image val5 = ((Component)val3).gameObject.AddComponent<Image>();
		val5.preserveAspect = true;
		((Graphic)val5).raycastTarget = false;
		TMP_Text val6 = ui.Text((Transform)(object)val, "Name", "", T.bodySize);
		val6.richText = true;
		RectTransform val7 = (RectTransform)val6.transform;
		PickerControls.Stretch(val7);
		val7.offsetMin = new Vector2(T.listRowPadding * 2f + T.listIconSize, 0f);
		val7.offsetMax = new Vector2(0f - T.listRowPadding, 0f);
		return new Row
		{
			Button = button,
			Icon = val5,
			Label = val6,
			Selection = val2,
			Tooltip = ui.Tooltip(((Component)val).gameObject, "")
		};
	}

	internal void SelectIndex(int index)
	{
		if (interactable && index >= 0 && index < items.Count)
		{
			string id = items[index].Id;
			if (!(selectedId == id))
			{
				SetSelection(id);
				selected(id);
			}
		}
	}

	internal void ActivateIndex(int index)
	{
		if (interactable && index >= 0 && index < items.Count && activated != null)
		{
			SelectIndex(index);
			activated(items[index].Id);
		}
	}

	internal void Move(int current, int delta)
	{
		//IL_004f: 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_0070: 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_00cb: 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)
		if (!interactable || items.Count == 0)
		{
			return;
		}
		int num = Mathf.Clamp(current + delta, 0, items.Count - 1);
		float num2 = (float)num * T.listRowHeight;
		float y = content.anchoredPosition.y;
		if (num2 < y)
		{
			content.anchoredPosition = new Vector2(0f, num2);
		}
		else
		{
			float num3 = num2 + T.listRowHeight;
			Rect rect = viewport.rect;
			if (num3 > y + ((Rect)(ref rect)).height)
			{
				RectTransform obj = content;
				float num4 = num2 + T.listRowHeight;
				rect = viewport.rect;
				obj.anchoredPosition = new Vector2(0f, num4 - ((Rect)(ref rect)).height);
			}
		}
		RefreshVisible();
		SelectIndex(num);
		foreach (Row row in rows)
		{
			if (row.Button.Index == num && ((Component)row.Button).gameObject.activeInHierarchy)
			{
				((Selectable)row.Button).Select();
				break;
			}
		}
	}

	internal void ConnectHorizontal(Selectable target)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: 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)
		foreach (Row row in rows)
		{
			Navigation navigation = ((Selectable)row.Button).navigation;
			((Navigation)(ref navigation)).mode = (Mode)4;
			Selectable selectOnLeft = (((Navigation)(ref navigation)).selectOnRight = target);
			((Navigation)(ref navigation)).selectOnLeft = selectOnLeft;
			((Selectable)row.Button).navigation = navigation;
		}
	}
}
internal sealed class PickerRowButton : Button
{
	internal PickerListView Owner;

	internal int Index;

	internal string ItemId;

	private readonly RowClickSequence clicks = new RowClickSequence();

	public override void OnPointerClick(PointerEventData data)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Invalid comparison between Unknown and I4
		bool flag = clicks.Register(ItemId, data.clickCount, (int)data.button == 0, ((UIBehaviour)this).IsActive() && ((Selectable)this).IsInteractable());
		((Button)this).OnPointerClick(data);
		if (flag)
		{
			Owner?.ActivateIndex(Index);
		}
	}

	protected override void OnDisable()
	{
		clicks.Reset();
		((Selectable)this).OnDisable();
	}

	public override void OnMove(AxisEventData data)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Invalid comparison between Unknown and I4
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Invalid comparison between Unknown and I4
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Invalid comparison between Unknown and I4
		if ((int)data.moveDir == 1 || (int)data.moveDir == 3)
		{
			Owner?.Move(Index, ((int)data.moveDir != 1) ? 1 : (-1));
			((AbstractEventData)data).Use();
		}
		else
		{
			((Selectable)this).OnMove(data);
		}
	}

	public override void OnSelect(BaseEventData data)
	{
		((Selectable)this).OnSelect(data);
		Owner?.SelectIndex(Index);
	}
}
internal sealed class PickerViewportWatcher : MonoBehaviour
{
	internal PickerListView Owner;

	private void OnRectTransformDimensionsChange()
	{
		Owner?.RefreshVisible();
	}

	private void OnEnable()
	{
		Owner?.RefreshVisible();
	}
}
internal sealed class PickerModel
{
	internal static readonly string[] CategoryKeys = new string[6] { "all", "materials", "food", "equipment", "tools", "other" };

	private readonly List<string> draft = new List<string>();

	private readonly HashSet<string> categories = new HashSet<string>(StringComparer.Ordinal);

	internal IReadOnlyList<string> Draft { get; }

	internal string LeftId { get; private set; }

	internal string RightId { get; private set; }

	internal string Search { get; set; } = "";

	internal bool AllCategories => categories.Count == 0;

	internal bool CanAdd => LeftId != null && !draft.Contains(LeftId);

	internal bool CanRemove => RightId != null && draft.Contains(RightId);

	internal PickerModel()
	{
		Draft = draft.AsReadOnly();
	}

	internal void Load(IEnumerable<string> ids)
	{
		draft.Clear();
		foreach (string item in ids.Where((string id) => !string.IsNullOrEmpty(id)).Distinct<string>(StringComparer.Ordinal))
		{
			draft.Add(item);
		}
		string leftId = (RightId = null);
		LeftId = leftId;
		Search = "";
		categories.Clear();
	}

	internal bool CategoryChecked(string key)
	{

BepInEx/plugins/ChestItemFilter/VanillaChestItemCategory.dll

Decompiled 15 hours ago
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using VanillaChestItemCategory;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("VanillaChestItemCategory")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+627c93de35fe4ea8fc7db780adf6d890daf2a24a")]
[assembly: AssemblyProduct("VanillaChestItemCategory")]
[assembly: AssemblyTitle("VanillaChestItemCategory")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: TypeForwardedTo(typeof(StorageFilter))]
[assembly: TypeForwardedTo(typeof(StorageFilterCompatibility))]
[assembly: TypeForwardedTo(typeof(StorageFilterCore))]
[assembly: TypeForwardedTo(typeof(StorageFilterPersistence))]
[assembly: TypeForwardedTo(typeof(StorageFilterRouting))]