Decompiled source of LootFilterUI v0.0.2

plugins\ValheimLootFilter.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.GUI;
using Jotunn.Managers;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ValheimLootFilter")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ValheimLootFilter")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.2")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.2.0")]
namespace ValheimLootFilter;

[HarmonyPatch(typeof(InventoryGui), "Awake")]
public static class InventoryGuiPatch
{
	private const string ButtonName = "lootfilter_button";

	private const string IconItemPrefab = "Coins";

	private const float FallbackGap = 8f;

	private const float SideMargin = 8f;

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

	[HarmonyPostfix]
	public static void Postfix(InventoryGui __instance)
	{
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Expected O, but got Unknown
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Invalid comparison between Unknown and I4
		Toggle pvp = __instance.m_pvp;
		if ((Object)(object)pvp == (Object)null)
		{
			Logger.LogWarning((object)"[LootFilter] m_pvp not found — skipping button injection");
			return;
		}
		Transform parent = ((Component)pvp).transform.parent;
		if ((Object)(object)parent.Find("lootfilter_button") != (Object)null)
		{
			return;
		}
		Button val = FindTrophiesButton(parent, pvp);
		if ((Object)(object)val == (Object)null)
		{
			Logger.LogWarning((object)"[LootFilter] Trophies button not found — skipping button injection");
			return;
		}
		GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent);
		((Object)val2).name = "lootfilter_button";
		Button component = val2.GetComponent<Button>();
		component.onClick = new ButtonClickedEvent();
		((UnityEvent)component.onClick).AddListener(new UnityAction(LootFilterUI.TogglePanel));
		TMP_Text componentInChildren = val2.GetComponentInChildren<TMP_Text>();
		if ((Object)(object)componentInChildren != (Object)null)
		{
			componentInChildren.text = "Loot Filter";
		}
		else
		{
			Text componentInChildren2 = val2.GetComponentInChildren<Text>();
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				componentInChildren2.text = "Loot Filter";
			}
		}
		UITooltip componentInChildren3 = val2.GetComponentInChildren<UITooltip>();
		if ((Object)(object)componentInChildren3 != (Object)null)
		{
			componentInChildren3.m_topic = "";
			componentInChildren3.m_text = "Loot Filter";
		}
		Image val3 = FindIconImage(val2);
		if ((Object)(object)val3 != (Object)null)
		{
			if ((int)((Selectable)component).transition == 2 && (Object)(object)((Selectable)component).targetGraphic == (Object)(object)val3)
			{
				((Selectable)component).transition = (Transition)1;
			}
			((MonoBehaviour)__instance).StartCoroutine(SwapIconWhenReady(val3));
		}
		else
		{
			Logger.LogWarning((object)"[LootFilter] No icon Image found on cloned button — keeping trophy icon");
		}
		LayoutRow(parent, ((Component)val).GetComponent<RectTransform>(), val2.GetComponent<RectTransform>());
		Logger.LogInfo((object)"[LootFilter] Loot Filter button injected into InventoryGui");
	}

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

	private static Image FindIconImage(GameObject buttonGO)
	{
		Image val = null;
		Image[] componentsInChildren = buttonGO.GetComponentsInChildren<Image>(true);
		foreach (Image val2 in componentsInChildren)
		{
			if (!((Object)(object)((Component)val2).gameObject == (Object)(object)buttonGO))
			{
				val = val2;
			}
		}
		if (!((Object)(object)val != (Object)null))
		{
			return buttonGO.GetComponent<Image>();
		}
		return val;
	}

	private static IEnumerator SwapIconWhenReady(Image iconImage)
	{
		while ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_items.Count == 0)
		{
			yield return null;
		}
		if ((Object)(object)iconImage == (Object)null)
		{
			yield break;
		}
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Coins");
		object obj;
		if (!((Object)(object)itemPrefab != (Object)null))
		{
			obj = null;
		}
		else
		{
			ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
			if (component == null)
			{
				obj = null;
			}
			else
			{
				ItemData itemData = component.m_itemData;
				obj = ((itemData != null) ? itemData.GetIcon() : null);
			}
		}
		Sprite val = (Sprite)obj;
		if ((Object)(object)val != (Object)null)
		{
			iconImage.sprite = val;
		}
		else
		{
			Logger.LogWarning((object)"[LootFilter] Could not resolve icon sprite from prefab 'Coins'");
		}
	}

	private static void LayoutRow(Transform bar, RectTransform trophiesRT, RectTransform insertedRT)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Expected O, but got Unknown
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Expected O, but got Unknown
		//IL_019f: Expected O, but got Unknown
		//IL_0283: Unknown result type (might be due to invalid IL or missing references)
		//IL_0288: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
		List<RectTransform> list = new List<RectTransform>();
		foreach (Transform item in bar)
		{
			Transform val = item;
			if (((Component)val).gameObject.activeSelf && !((Object)(object)val == (Object)(object)((Component)insertedRT).transform) && !((Object)(object)((Component)val).GetComponent<Selectable>() == (Object)null))
			{
				list.Add((RectTransform)val);
			}
		}
		if (list.Count == 0)
		{
			return;
		}
		list.Sort((RectTransform a, RectTransform b) => WorldLeft(a).CompareTo(WorldLeft(b)));
		float num = bar.lossyScale.x;
		if (num <= 0f)
		{
			num = 1f;
		}
		List<float> list2 = new List<float>();
		for (int num2 = 1; num2 < list.Count; num2++)
		{
			list2.Add(WorldLeft(list[num2]) - WorldRight(list[num2 - 1]));
		}
		list2.Sort();
		float num3 = ((list2.Count > 0) ? list2[list2.Count / 2] : (8f * num));
		int num4 = list.IndexOf(trophiesRT);
		list.Insert((num4 >= 0) ? (num4 + 1) : list.Count, insertedRT);
		float num5 = 0f;
		foreach (RectTransform item2 in list)
		{
			num5 += WorldRight(item2) - WorldLeft(item2);
		}
		RectTransform val2 = (RectTransform)bar;
		float num6 = WorldLeft(val2);
		float num7 = WorldRight(val2);
		float num8 = num7 - num6;
		float num9 = Mathf.Min(8f * num, Mathf.Max(0f, (num8 - num5) * 0.5f));
		float num10 = ((list.Count > 1) ? ((num8 - 2f * num9 - num5) / (float)(list.Count - 1)) : 0f);
		float num11 = Mathf.Max(0f, Mathf.Min(num3, num10));
		float num12 = num7 - num9;
		if (num8 < num5)
		{
			Logger.LogWarning((object)$"[LootFilter] Bar rect ({num8 / num:F0}) narrower than buttons ({num5 / num:F0}) — ignoring section bounds");
			num12 = WorldRight(list[list.Count - 1]);
		}
		for (int num13 = list.Count - 1; num13 >= 0; num13--)
		{
			float num14 = WorldLeft(list[num13]);
			float num15 = WorldRight(list[num13]) - num14;
			float num16 = num12 - num15;
			Vector2 anchoredPosition = list[num13].anchoredPosition;
			anchoredPosition.x += (num16 - num14) / num;
			list[num13].anchoredPosition = anchoredPosition;
			num12 = num16 - num11;
		}
	}

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

	private static float WorldRight(RectTransform rt)
	{
		rt.GetWorldCorners(Corners);
		return Corners[2].x;
	}
}
public static class LootFilterService
{
	[HarmonyPatch]
	public static class Patches
	{
		[HarmonyPatch(typeof(Player), "AutoPickup")]
		[HarmonyPrefix]
		private static bool AutoPickup_Prefix(Player __instance)
		{
			return true;
		}

		[HarmonyPatch(typeof(ItemDrop), "CanPickup")]
		[HarmonyPostfix]
		private static void CanPickup_Postfix(ItemDrop __instance, ref bool __result)
		{
			if (__result && IsExcluded(((Object)((Component)__instance).gameObject).name.Replace("(Clone)", "").Trim()))
			{
				__result = false;
			}
		}
	}

	private static ConfigEntry<string> _cfgExcluded;

	private static readonly HashSet<string> ExcludedItems = new HashSet<string>();

	public static void Init(ConfigFile config)
	{
		_cfgExcluded = config.Bind<string>("LootFilter", "ExcludedItems", "", "Comma-separated list of prefab names excluded from auto-pickup");
		foreach (string item in from s in _cfgExcluded.Value.Split(new char[1] { ',' })
			select s.Trim() into s
			where s.Length > 0
			select s)
		{
			ExcludedItems.Add(item);
		}
	}

	public static bool IsExcluded(string prefabName)
	{
		return ExcludedItems.Contains(prefabName);
	}

	public static bool ToggleExcluded(string prefabName)
	{
		bool result;
		if (ExcludedItems.Contains(prefabName))
		{
			ExcludedItems.Remove(prefabName);
			result = false;
		}
		else
		{
			ExcludedItems.Add(prefabName);
			result = true;
		}
		Save();
		return result;
	}

	private static void Save()
	{
		if (_cfgExcluded != null)
		{
			_cfgExcluded.Value = string.Join(",", ExcludedItems);
		}
	}

	public static List<ItemDrop> GetAllItems()
	{
		if (!((Object)(object)ObjectDB.instance == (Object)null))
		{
			return (from go in ObjectDB.instance.m_items
				select go.GetComponent<ItemDrop>() into id
				where (Object)(object)id != (Object)null
				select id).ToList();
		}
		return new List<ItemDrop>();
	}
}
public static class LootFilterUI
{
	private static GameObject _filtersPanel;

	private static GameObject _scrollView;

	private static Transform _contentRoot;

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

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

	private static readonly Color ColExcluded = new Color(1f, 0.2f, 0.2f, 1f);

	private const float PanelW = 1050f;

	private const float PanelH = 800f;

	private const float ScrollW = 970f;

	private const float ScrollH = 650f;

	private const float CellSize = 64f;

	private const float CellSpacing = 8f;

	private const float GroupHeaderH = 30f;

	private const float GroupHeaderFontSize = 18f;

	public static void TogglePanel()
	{
		if (!Object.op_Implicit((Object)(object)_filtersPanel))
		{
			BuildPanel();
		}
		bool flag = !_filtersPanel.activeSelf;
		_filtersPanel.SetActive(flag);
		GUIManager.BlockInput(flag);
		if (flag)
		{
			RefreshContent();
		}
	}

	private static void BuildPanel()
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: 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_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ac: Expected O, but got Unknown
		//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: Unknown result type (might be due to invalid IL or missing references)
		//IL_0330: Unknown result type (might be due to invalid IL or missing references)
		//IL_033a: Expected O, but got Unknown
		if (GUIManager.Instance == null || !Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront))
		{
			Logger.LogError((object)"GUIManager not ready");
			return;
		}
		_filtersPanel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 1050f, 800f, true);
		_filtersPanel.SetActive(false);
		if (!Object.op_Implicit((Object)(object)_filtersPanel.GetComponent<DragWindowCntrl>()))
		{
			_filtersPanel.AddComponent<DragWindowCntrl>();
		}
		GUIManager.Instance.CreateText("Loot Filter", _filtersPanel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -20f), GUIManager.Instance.AveriaSerifBold, 30, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false).GetComponent<RectTransform>().pivot = new Vector2(0.5f, 1f);
		GUIManager.Instance.CreateText("Click an item to toggle auto-pickup exclusion  [ red = excluded ]", _filtersPanel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -56f), GUIManager.Instance.AveriaSerifBold, 13, Color.white, true, Color.black, 700f, 24f, false).GetComponent<RectTransform>().pivot = new Vector2(0.5f, 1f);
		_scrollView = GUIManager.Instance.CreateScrollView(_filtersPanel.transform, false, true, 5f, 2f, GUIManager.Instance.ValheimScrollbarHandleColorBlock, GUIManager.Instance.ValheimBeige, 970f, 650f);
		RectTransform component = _scrollView.GetComponent<RectTransform>();
		component.anchorMin = new Vector2(0.5f, 1f);
		component.anchorMax = new Vector2(0.5f, 1f);
		component.pivot = new Vector2(0.5f, 1f);
		component.anchoredPosition = new Vector2(0f, -80f);
		ScrollRect componentInChildren = _scrollView.GetComponentInChildren<ScrollRect>();
		if ((Object)(object)componentInChildren == (Object)null)
		{
			Logger.LogError((object)"ScrollRect not found inside CreateScrollView result");
			return;
		}
		_contentRoot = (Transform)(object)componentInChildren.content;
		VerticalLayoutGroup orAddComponent = ((Component)_contentRoot).gameObject.GetOrAddComponent<VerticalLayoutGroup>();
		((LayoutGroup)orAddComponent).childAlignment = (TextAnchor)0;
		((HorizontalOrVerticalLayoutGroup)orAddComponent).childControlHeight = false;
		((HorizontalOrVerticalLayoutGroup)orAddComponent).childControlWidth = false;
		((HorizontalOrVerticalLayoutGroup)orAddComponent).childForceExpandHeight = false;
		((HorizontalOrVerticalLayoutGroup)orAddComponent).childForceExpandWidth = false;
		((HorizontalOrVerticalLayoutGroup)orAddComponent).spacing = 10f;
		((LayoutGroup)orAddComponent).padding = new RectOffset(10, 10, 10, 10);
		ContentSizeFitter orAddComponent2 = ((Component)_contentRoot).gameObject.GetOrAddComponent<ContentSizeFitter>();
		orAddComponent2.verticalFit = (FitMode)2;
		orAddComponent2.horizontalFit = (FitMode)0;
		GameObject obj = GUIManager.Instance.CreateButton("Close", _filtersPanel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 40f), 250f, 60f);
		obj.SetActive(true);
		((UnityEvent)obj.GetComponent<Button>().onClick).AddListener(new UnityAction(TogglePanel));
	}

	private static void RefreshContent()
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_contentRoot == (Object)null)
		{
			Logger.LogError((object)"Content root is null — panel was not built correctly");
			return;
		}
		foreach (Transform item in _contentRoot)
		{
			Object.Destroy((Object)(object)((Component)item).gameObject);
		}
		List<ItemDrop> allItems = LootFilterService.GetAllItems();
		Logger.LogInfo((object)$"Found {allItems.Count} total items in ObjectDB");
		HashSet<string> knownNames = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.m_knownMaterial : new HashSet<string>());
		Logger.LogInfo((object)$"{knownNames.Count} items are known");
		foreach (string item2 in knownNames)
		{
			Logger.LogInfo((object)("Known item: " + item2));
		}
		IOrderedEnumerable<IGrouping<ItemType, ItemDrop>> orderedEnumerable = from i in allItems
			group i by (ItemType)(((??)i.m_itemData?.m_shared?.m_itemType) ?? 16) into g
			orderby ((object)g.Key/*cast due to .constrained prefix*/).ToString()
			select g;
		Logger.LogInfo((object)$"{orderedEnumerable.Count()} groups will be created");
		foreach (IGrouping<ItemType, ItemDrop> item3 in orderedEnumerable)
		{
			List<ItemDrop> list = item3.Where((ItemDrop i) => knownNames.Count == 0 || knownNames.Contains(i.m_itemData?.m_shared?.m_name)).ToList();
			if (list.Count == 0)
			{
				Logger.LogInfo((object)$"{item3.Key} group has no discovered items, skipping...");
			}
			else
			{
				CreateGroupSection(((object)item3.Key/*cast due to .constrained prefix*/).ToString(), list);
			}
		}
		Transform contentRoot = _contentRoot;
		LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((contentRoot is RectTransform) ? contentRoot : null));
	}

	private static void CreateGroupSection(string categoryName, List<ItemDrop> items)
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		//IL_0060: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Expected O, but got Unknown
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		Logger.LogInfo((object)$"Creating section for category '{categoryName}' with {items.Count} items");
		GameObject val = new GameObject("Section_" + categoryName, new Type[1] { typeof(RectTransform) });
		val.transform.SetParent(_contentRoot, false);
		val.GetComponent<RectTransform>().sizeDelta = new Vector2(946f, 0f);
		VerticalLayoutGroup obj = val.AddComponent<VerticalLayoutGroup>();
		((LayoutGroup)obj).childAlignment = (TextAnchor)0;
		((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false;
		((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false;
		((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
		((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false;
		((HorizontalOrVerticalLayoutGroup)obj).spacing = 4f;
		ContentSizeFitter obj2 = val.AddComponent<ContentSizeFitter>();
		obj2.verticalFit = (FitMode)2;
		obj2.horizontalFit = (FitMode)0;
		GameObject obj3 = GUIManager.Instance.CreateText(categoryName, val.transform, new Vector2(0f, 1f), new Vector2(1f, 1f), Vector2.zero, GUIManager.Instance.AveriaSerifBold, 18, GUIManager.Instance.ValheimOrange, true, Color.black, 946f, 30f, false);
		RectTransform component = obj3.GetComponent<RectTransform>();
		component.pivot = new Vector2(0f, 1f);
		component.sizeDelta = new Vector2(946f, 30f);
		Text component2 = obj3.GetComponent<Text>();
		if (Object.op_Implicit((Object)(object)component2))
		{
			component2.alignment = (TextAnchor)3;
		}
		GameObject val2 = new GameObject("Grid_" + categoryName, new Type[1] { typeof(RectTransform) });
		val2.transform.SetParent(val.transform, false);
		val2.GetComponent<RectTransform>().sizeDelta = new Vector2(946f, 0f);
		GridLayoutGroup obj4 = val2.AddComponent<GridLayoutGroup>();
		obj4.cellSize = new Vector2(64f, 64f);
		obj4.spacing = new Vector2(8f, 8f);
		obj4.startCorner = (Corner)0;
		obj4.startAxis = (Axis)0;
		((LayoutGroup)obj4).childAlignment = (TextAnchor)0;
		obj4.constraint = (Constraint)1;
		int num = Mathf.FloorToInt(13.25f);
		obj4.constraintCount = Mathf.Max(1, num);
		ContentSizeFitter obj5 = val2.AddComponent<ContentSizeFitter>();
		obj5.verticalFit = (FitMode)2;
		obj5.horizontalFit = (FitMode)0;
		foreach (ItemDrop item in items)
		{
			CreateItemCell(val2.transform, item);
		}
	}

	private static void CreateItemCell(Transform parent, ItemDrop item)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		//IL_006d: 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_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: 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_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: Unknown result type (might be due to invalid IL or missing references)
		//IL_0228: Unknown result type (might be due to invalid IL or missing references)
		//IL_024e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d0: Expected O, but got Unknown
		//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02da: 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_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0325: Unknown result type (might be due to invalid IL or missing references)
		bool flag = LootFilterService.IsExcluded(((Object)item).name);
		GameObject val = new GameObject("Cell_" + ((Object)item).name, new Type[1] { typeof(RectTransform) });
		val.transform.SetParent(parent, false);
		Button val2 = val.AddComponent<Button>();
		Image val3 = val.AddComponent<Image>();
		((Graphic)val3).color = new Color(0f, 0f, 0f, 0.45f);
		GameObject val4 = new GameObject("Icon", new Type[1] { typeof(RectTransform) });
		val4.transform.SetParent(val.transform, false);
		RectTransform component = val4.GetComponent<RectTransform>();
		component.anchorMin = new Vector2(0.1f, 0.1f);
		component.anchorMax = new Vector2(0.9f, 0.9f);
		component.offsetMin = Vector2.zero;
		component.offsetMax = Vector2.zero;
		Image val5 = val4.AddComponent<Image>();
		Sprite itemSprite = GetItemSprite(item);
		if (Object.op_Implicit((Object)(object)itemSprite))
		{
			val5.sprite = itemSprite;
		}
		((Graphic)val5).color = (flag ? ColExcluded : ColNormal);
		GameObject val6 = GUIManager.Instance.CreateText("✕", val.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, GUIManager.Instance.AveriaSerifBold, 28, new Color(1f, 0.15f, 0.15f, 0.9f), true, Color.black, 64f, 64f, false);
		val6.SetActive(flag);
		string text = item.m_itemData?.m_shared?.m_name ?? ((Object)item).name;
		if (Localization.instance != null && text.StartsWith("$"))
		{
			text = Localization.instance.Localize(text);
		}
		GameObject obj = GUIManager.Instance.CreateText(text, val.transform, new Vector2(0f, 0f), new Vector2(1f, 0f), Vector2.zero, GUIManager.Instance.AveriaSerifBold, 7, Color.white, true, Color.black, 64f, 14f, false);
		RectTransform component2 = obj.GetComponent<RectTransform>();
		component2.pivot = new Vector2(0.5f, 0f);
		component2.anchoredPosition = new Vector2(0f, 0f);
		Text component3 = obj.GetComponent<Text>();
		if (Object.op_Implicit((Object)(object)component3))
		{
			component3.alignment = (TextAnchor)4;
			component3.resizeTextForBestFit = true;
			component3.resizeTextMinSize = 5;
			component3.resizeTextMaxSize = 9;
		}
		string itemName = ((Object)item).name;
		Image capturedIcon = val5;
		GameObject capturedX = val6;
		((UnityEvent)val2.onClick).AddListener((UnityAction)delegate
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			bool flag2 = LootFilterService.ToggleExcluded(itemName);
			((Graphic)capturedIcon).color = (flag2 ? ColExcluded : ColNormal);
			capturedX.SetActive(flag2);
			Logger.LogInfo((object)$"[LootFilter] {itemName} excluded={flag2}");
		});
		ColorBlock colors = ((Selectable)val2).colors;
		((ColorBlock)(ref colors)).normalColor = Color.white;
		((ColorBlock)(ref colors)).highlightedColor = new Color(1.3f, 1.3f, 0.7f, 1f);
		((ColorBlock)(ref colors)).pressedColor = new Color(0.7f, 0.7f, 0.7f, 1f);
		((Selectable)val2).colors = colors;
		((Selectable)val2).targetGraphic = (Graphic)(object)val3;
	}

	private static Sprite GetItemSprite(ItemDrop item)
	{
		if (_iconCache.TryGetValue(((Object)item).name, out var value))
		{
			return value;
		}
		ItemData itemData = item.m_itemData;
		Sprite val = ((itemData != null && itemData.m_shared?.m_icons?.Length > 0) ? item.m_itemData.m_shared.m_icons[0] : null);
		_iconCache[((Object)item).name] = val;
		return val;
	}
}
internal static class GameObjectExtensions
{
	public static T GetOrAddComponent<T>(this GameObject go) where T : Component
	{
		return go.GetComponent<T>() ?? go.AddComponent<T>();
	}
}
[BepInPlugin("com.ukie.ValheimLootFilter", "LootFilter", "0.0.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal class ValheimLootFilter : BaseUnityPlugin
{
	public const string PluginGUID = "com.ukie.ValheimLootFilter";

	public const string PluginName = "LootFilter";

	public const string PluginVersion = "0.0.2";

	public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

	private Harmony _harmony;

	private ButtonConfig LootFilterShortcutButton;

	private void Awake()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Expected O, but got Unknown
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Expected O, but got Unknown
		LootFilterService.Init(((BaseUnityPlugin)this).Config);
		LootFilterShortcutButton = new ButtonConfig
		{
			Name = "ValheimLootFiler_ShortcutButton",
			Key = (KeyCode)108
		};
		InputManager.Instance.AddButton("com.ukie.ValheimLootFilter", LootFilterShortcutButton);
		_harmony = new Harmony("com.ukie.ValheimLootFilter");
		_harmony.PatchAll(typeof(LootFilterService.Patches));
		_harmony.PatchAll(typeof(InventoryGuiPatch));
		Logger.LogInfo((object)"LootFilter has landed");
	}

	private void Update()
	{
		if (ZInput.instance != null && ZInput.GetButtonDown(LootFilterShortcutButton.Name))
		{
			LootFilterUI.TogglePanel();
		}
	}
}