Decompiled source of ItemSearch v1.0.0

ItemSearch.dll

Decompiled 15 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ItemSearch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ItemSearch")]
[assembly: AssemblyTitle("ItemSearch")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ItemSearch
{
	internal sealed class ItemEntry
	{
		public string Token;

		public string DisplayName;

		public Sprite Icon;

		public int Total;

		public readonly List<Container> Containers = new List<Container>();
	}
	internal sealed class ScanResult
	{
		public readonly Dictionary<string, ItemEntry> Items = new Dictionary<string, ItemEntry>();

		public int ContainerCount;

		public List<ItemEntry> Filter(string query)
		{
			query = query?.Trim() ?? "";
			return Items.Values.Where((ItemEntry e) => query.Length == 0 || ContainerScanner.Matches(e, query)).OrderBy<ItemEntry, string>((ItemEntry e) => e.DisplayName, StringComparer.CurrentCultureIgnoreCase).ToList();
		}

		public List<ItemEntry> Resolve(string query, string selectedToken)
		{
			query = query?.Trim() ?? "";
			if (selectedToken != null && Items.TryGetValue(selectedToken, out var value) && string.Equals(value.DisplayName, query, StringComparison.CurrentCultureIgnoreCase))
			{
				return new List<ItemEntry> { value };
			}
			if (query.Length == 0)
			{
				return new List<ItemEntry>();
			}
			List<ItemEntry> list = Items.Values.Where((ItemEntry e) => string.Equals(e.DisplayName, query, StringComparison.CurrentCultureIgnoreCase)).ToList();
			if (list.Count <= 0)
			{
				return Filter(query);
			}
			return list;
		}
	}
	internal static class ContainerScanner
	{
		private static readonly FieldRef<Container, ZNetView> ContainerNView = AccessTools.FieldRefAccess<Container, ZNetView>("m_nview");

		private static int _mask;

		private static int Mask
		{
			get
			{
				if (_mask == 0)
				{
					_mask = LayerMask.GetMask(new string[4] { "piece", "piece_nonsolid", "vehicle", "Default" });
				}
				return _mask;
			}
		}

		public static bool Matches(ItemEntry entry, string query)
		{
			return entry.DisplayName.IndexOf(query, StringComparison.CurrentCultureIgnoreCase) >= 0;
		}

		public static ScanResult Scan(Vector3 center, float radius)
		{
			//IL_000c: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			ScanResult scanResult = new ScanResult();
			HashSet<Container> hashSet = new HashSet<Container>();
			Collider[] array = Physics.OverlapSphere(center, radius, Mask, (QueryTriggerInteraction)2);
			float num = radius * radius;
			Collider[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				Container componentInParent = ((Component)array2[i]).GetComponentInParent<Container>();
				if ((Object)(object)componentInParent == (Object)null || !hashSet.Add(componentInParent) || !IsUsable(componentInParent))
				{
					continue;
				}
				Vector3 val = ((Component)componentInParent).transform.position - center;
				if (((Vector3)(ref val)).sqrMagnitude > num)
				{
					continue;
				}
				scanResult.ContainerCount++;
				foreach (ItemData allItem in componentInParent.GetInventory().GetAllItems())
				{
					if (allItem?.m_shared == null)
					{
						continue;
					}
					string name = allItem.m_shared.m_name;
					if (!string.IsNullOrEmpty(name))
					{
						if (!scanResult.Items.TryGetValue(name, out var value))
						{
							value = new ItemEntry
							{
								Token = name,
								DisplayName = Localize(name),
								Icon = SafeIcon(allItem)
							};
							scanResult.Items.Add(name, value);
						}
						value.Total += allItem.m_stack;
						if (!value.Containers.Contains(componentInParent))
						{
							value.Containers.Add(componentInParent);
						}
					}
				}
			}
			return scanResult;
		}

		private static bool IsUsable(Container container)
		{
			ZNetView val = ContainerNView.Invoke(container);
			if ((Object)(object)val != (Object)null && val.IsValid())
			{
				return container.GetInventory() != null;
			}
			return false;
		}

		private static string Localize(string token)
		{
			Localization instance = Localization.instance;
			if (instance == null)
			{
				return token;
			}
			return instance.Localize(token);
		}

		private static Sprite SafeIcon(ItemData item)
		{
			try
			{
				return item.GetIcon();
			}
			catch
			{
				return null;
			}
		}
	}
	internal sealed class GuideLines : MonoBehaviour
	{
		private sealed class Guide
		{
			public Container Target;

			public Effect Line;

			public Effect Beacon;
		}

		private sealed class Effect
		{
			private readonly GameObject _go;

			private readonly ParticleSystem[] _systems;

			private readonly float[] _baseRate;

			private readonly int[] _baseMax;

			private float _appliedLength = -1f;

			public Effect(GameObject go)
			{
				//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_007b: 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)
				_go = go;
				_systems = go.GetComponentsInChildren<ParticleSystem>(true);
				_baseRate = new float[_systems.Length];
				_baseMax = new int[_systems.Length];
				for (int i = 0; i < _systems.Length; i++)
				{
					float[] baseRate = _baseRate;
					int num = i;
					EmissionModule emission = _systems[i].emission;
					baseRate[num] = ((EmissionModule)(ref emission)).rateOverTimeMultiplier;
					int[] baseMax = _baseMax;
					int num2 = i;
					MainModule main = _systems[i].main;
					baseMax[num2] = ((MainModule)(ref main)).maxParticles;
				}
			}

			public void Set(Vector3 from, Vector3 to)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: 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_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ad: 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_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)
				if ((Object)(object)_go == (Object)null)
				{
					return;
				}
				Vector3 val = to - from;
				float magnitude = ((Vector3)(ref val)).magnitude;
				if (magnitude < 0.01f)
				{
					return;
				}
				Transform transform = _go.transform;
				transform.position = from;
				transform.rotation = Quaternion.LookRotation(val / magnitude);
				transform.localScale = new Vector3(1f, 1f, magnitude);
				if (!(Mathf.Abs(magnitude - _appliedLength) > 0.5f))
				{
					return;
				}
				_appliedLength = magnitude;
				float num = Mathf.Max(1f, magnitude / 5f);
				for (int i = 0; i < _systems.Length; i++)
				{
					if (!((Object)(object)_systems[i] == (Object)null))
					{
						EmissionModule emission = _systems[i].emission;
						((EmissionModule)(ref emission)).rateOverTimeMultiplier = _baseRate[i] * num;
						MainModule main = _systems[i].main;
						((MainModule)(ref main)).maxParticles = Mathf.CeilToInt((float)_baseMax[i] * num);
					}
				}
			}

			public void Destroy()
			{
				if ((Object)(object)_go != (Object)null)
				{
					Object.Destroy((Object)(object)_go);
				}
			}
		}

		private const float PlayerHeight = 1.1f;

		private const float ChestHeight = 0.6f;

		private const float BeaconHeight = 8f;

		private const float VanillaLinkLength = 5f;

		private readonly List<Guide> _guides = new List<Guide>();

		private GameObject _connectionPrefab;

		public bool HasLines => _guides.Count > 0;

		public bool Targets(Container container)
		{
			foreach (Guide guide in _guides)
			{
				if ((Object)(object)guide.Target == (Object)(object)container)
				{
					return true;
				}
			}
			return false;
		}

		public void Show(IEnumerable<Container> targets)
		{
			Clear();
			if ((Object)(object)GetConnectionPrefab() == (Object)null)
			{
				return;
			}
			foreach (Container target in targets)
			{
				if (!((Object)(object)target == (Object)null))
				{
					_guides.Add(new Guide
					{
						Target = target,
						Line = CreateEffect("ItemSearch_Line"),
						Beacon = (Plugin.ShowBeacon.Value ? CreateEffect("ItemSearch_Beacon") : null)
					});
				}
			}
			LateUpdate();
		}

		public void Clear()
		{
			foreach (Guide guide in _guides)
			{
				guide.Line.Destroy();
				guide.Beacon?.Destroy();
			}
			_guides.Clear();
		}

		private void LateUpdate()
		{
			//IL_0032: 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)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			if (_guides.Count == 0)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
			{
				Clear();
				return;
			}
			Vector3 val = ((Component)localPlayer).transform.position + Vector3.up * 1.1f;
			for (int num = _guides.Count - 1; num >= 0; num--)
			{
				Guide guide = _guides[num];
				if ((Object)(object)guide.Target == (Object)null)
				{
					guide.Line.Destroy();
					guide.Beacon?.Destroy();
					_guides.RemoveAt(num);
				}
				else
				{
					Vector3 val2 = ((Component)guide.Target).transform.position + Vector3.up * 0.6f;
					guide.Line.Set(val, val2);
					guide.Beacon?.Set(val2, val2 + Vector3.up * 8f);
				}
			}
		}

		private void OnDestroy()
		{
			Clear();
		}

		private GameObject GetConnectionPrefab()
		{
			if ((Object)(object)_connectionPrefab != (Object)null)
			{
				return _connectionPrefab;
			}
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			foreach (GameObject prefab in instance.m_prefabs)
			{
				StationExtension val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<StationExtension>() : null);
				if ((Object)(object)val != (Object)null && (Object)(object)val.m_connectionPrefab != (Object)null)
				{
					return _connectionPrefab = val.m_connectionPrefab;
				}
			}
			Plugin.LogWarning("Vanilla connection effect not found; no guide lines can be drawn.");
			return null;
		}

		private Effect CreateEffect(string name)
		{
			GameObject val = Object.Instantiate<GameObject>(_connectionPrefab, ((Component)this).transform);
			((Object)val).name = name;
			TimedDestruction[] componentsInChildren = val.GetComponentsInChildren<TimedDestruction>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.Destroy((Object)(object)componentsInChildren[i]);
			}
			return new Effect(val);
		}
	}
	[BepInPlugin("mythicalbird.valheim.itemsearch", "ItemSearch", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "mythicalbird.valheim.itemsearch";

		public const string ModName = "ItemSearch";

		public const string Version = "1.0.0";

		internal static Plugin Instance;

		internal static ConfigEntry<float> SearchRadius;

		internal static ConfigEntry<KeyboardShortcut> SearchKey;

		internal static ConfigEntry<bool> ShowBeacon;

		private static readonly FieldRef<InventoryGui, Container> CurrentContainer = AccessTools.FieldRefAccess<InventoryGui, Container>("m_currentContainer");

		private SearchPanel _panel;

		private GuideLines _lines;

		private void Awake()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			SearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SearchRadius", 50f, new ConfigDescription("Radius in meters around the player in which chests are searched.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>()));
			SearchKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "SearchKey", new KeyboardShortcut((KeyCode)284, Array.Empty<KeyCode>()), "Key that opens the item search panel.");
			ShowBeacon = ((BaseUnityPlugin)this).Config.Bind<bool>("Guide line", "ShowBeacon", true, "Draw a vertical column of dots above each matching chest.");
			_lines = new GameObject("ItemSearch_GuideLines").AddComponent<GuideLines>();
			Object.DontDestroyOnLoad((Object)(object)((Component)_lines).gameObject);
			_panel = new SearchPanel(_lines);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"ItemSearch 1.0.0 loaded");
		}

		private void Update()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				if (_panel.IsOpen)
				{
					_panel.Close();
				}
				return;
			}
			_panel.Update();
			if (!_panel.IsCapturingKey)
			{
				KeyboardShortcut value = SearchKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					if (_panel.IsOpen)
					{
						_panel.Close();
					}
					else if (CanOpenPanel())
					{
						_panel.Open();
					}
				}
			}
			if (_lines.HasLines && (Object)(object)InventoryGui.instance != (Object)null)
			{
				Container val = CurrentContainer.Invoke(InventoryGui.instance);
				if ((Object)(object)val != (Object)null && _lines.Targets(val))
				{
					_lines.Clear();
				}
			}
		}

		private void OnDestroy()
		{
			_panel?.Close();
		}

		private static bool CanOpenPanel()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
			{
				return false;
			}
			if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
			{
				return false;
			}
			if (Console.IsVisible() || TextInput.IsVisible() || Menu.IsVisible())
			{
				return false;
			}
			if (InventoryGui.IsVisible() || Minimap.IsOpen() || StoreGui.IsVisible())
			{
				return false;
			}
			return true;
		}

		internal static void LogWarning(string msg)
		{
			((BaseUnityPlugin)Instance).Logger.LogWarning((object)msg);
		}
	}
	internal sealed class SearchPanel
	{
		private sealed class Row
		{
			private readonly GameObject _go;

			private readonly Image _icon;

			private readonly Text _name;

			private readonly Text _count;

			private ItemEntry _entry;

			public Row(Transform parent, float y, Action<ItemEntry> onClick)
			{
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Expected O, but got Unknown
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				//IL_0079: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: 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_0080: 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_0087: 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_0094: 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_00bf: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_011a: 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_015a: 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_019c: Unknown result type (might be due to invalid IL or missing references)
				//IL_01af: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b9: Expected O, but got Unknown
				//IL_01de: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e4: Expected O, but got Unknown
				//IL_0201: Unknown result type (might be due to invalid IL or missing references)
				//IL_0206: Unknown result type (might be due to invalid IL or missing references)
				//IL_0207: Unknown result type (might be due to invalid IL or missing references)
				//IL_0219: Unknown result type (might be due to invalid IL or missing references)
				//IL_021f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0225: Unknown result type (might be due to invalid IL or missing references)
				//IL_0230: Unknown result type (might be due to invalid IL or missing references)
				//IL_0244: Unknown result type (might be due to invalid IL or missing references)
				//IL_0283: Unknown result type (might be due to invalid IL or missing references)
				//IL_0295: Unknown result type (might be due to invalid IL or missing references)
				//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_02e3: 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_0319: Unknown result type (might be due to invalid IL or missing references)
				//IL_0328: Unknown result type (might be due to invalid IL or missing references)
				Row row = this;
				_go = new GameObject("ResultRow", new Type[3]
				{
					typeof(RectTransform),
					typeof(Image),
					typeof(Button)
				});
				_go.transform.SetParent(parent, false);
				RectTransform val = (RectTransform)_go.transform;
				Vector2 val2 = (val.anchorMin = (val.anchorMax = TopCenter));
				val.anchoredPosition = new Vector2(0f, y);
				val.sizeDelta = new Vector2(400f, 34f);
				Image component = _go.GetComponent<Image>();
				((Graphic)component).color = Color.white;
				Button component2 = _go.GetComponent<Button>();
				((Selectable)component2).targetGraphic = (Graphic)(object)component;
				ColorBlock colors = default(ColorBlock);
				((ColorBlock)(ref colors)).normalColor = new Color(0f, 0f, 0f, 0.35f);
				((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 0.75f, 0.3f, 0.35f);
				((ColorBlock)(ref colors)).pressedColor = new Color(1f, 0.75f, 0.3f, 0.6f);
				((ColorBlock)(ref colors)).selectedColor = new Color(0f, 0f, 0f, 0.35f);
				((ColorBlock)(ref colors)).disabledColor = new Color(0f, 0f, 0f, 0.2f);
				((ColorBlock)(ref colors)).colorMultiplier = 1f;
				((ColorBlock)(ref colors)).fadeDuration = 0.08f;
				((Selectable)component2).colors = colors;
				((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
				{
					onClick(row._entry);
				});
				GameObject val4 = new GameObject("Icon", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				val4.transform.SetParent(_go.transform, false);
				RectTransform val5 = (RectTransform)val4.transform;
				((Vector2)(ref val2))..ctor(0f, 0.5f);
				val5.anchorMax = val2;
				val5.anchorMin = val2;
				val5.anchoredPosition = new Vector2(20f, 0f);
				val5.sizeDelta = new Vector2(30f, 30f);
				_icon = val4.GetComponent<Image>();
				_icon.preserveAspect = true;
				((Graphic)_icon).raycastTarget = false;
				_name = MakeText("", _go.transform, Vector2.zero, 270f, 34f, 17, (TextAnchor)3, TextColor);
				Anchor(((Graphic)_name).rectTransform, new Vector2(0f, 0.5f), new Vector2(42f, 0f));
				_count = MakeText("", _go.transform, Vector2.zero, 80f, 34f, 17, (TextAnchor)5, CountColor);
				Anchor(((Graphic)_count).rectTransform, new Vector2(1f, 0.5f), new Vector2(-10f, 0f));
				_go.SetActive(false);
			}

			public void Bind(ItemEntry entry)
			{
				_entry = entry;
				_go.SetActive(entry != null);
				if (entry != null)
				{
					_icon.sprite = entry.Icon;
					((Behaviour)_icon).enabled = (Object)(object)entry.Icon != (Object)null;
					_name.text = entry.DisplayName;
					_count.text = entry.Total.ToString("N0");
				}
			}

			private static void Anchor(RectTransform rt, Vector2 anchorAndPivot, Vector2 pos)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0004: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: 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_000d: 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)
				Vector2 val = (rt.pivot = anchorAndPivot);
				Vector2 anchorMin = (rt.anchorMax = val);
				rt.anchorMin = anchorMin;
				rt.anchoredPosition = pos;
			}
		}

		private const int MaxRows = 9;

		private const float Width = 440f;

		private const float Height = 580f;

		private const float RowWidth = 400f;

		private const float RowHeight = 34f;

		private const float RowStep = 38f;

		private const float RadiusStep = 5f;

		private static readonly Vector2 TopCenter = new Vector2(0.5f, 1f);

		private static readonly Color TextColor = new Color(1f, 0.89f, 0.7f);

		private static readonly Color DimText = new Color(0.8f, 0.75f, 0.65f);

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

		private static readonly KeyCode[] AllKeys = ((KeyCode[])Enum.GetValues(typeof(KeyCode))).Where((KeyCode k) => (int)k != 0 && (int)k != 323 && (int)k != 324 && (int)k < 330).ToArray();

		private readonly GuideLines _lines;

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

		private GameObject _root;

		private GameObject _searchView;

		private GameObject _settingsView;

		private GameObject _settingsButton;

		private InputField _query;

		private Text _status;

		private InputField _radiusField;

		private GameObject _keyButton;

		private ScanResult _snapshot;

		private string _selectedToken;

		private bool _suppressQueryChange;

		private bool _open;

		private bool _capturingKey;

		private int _keyCapturedFrame = -1;

		public bool IsOpen => _open;

		public bool IsCapturingKey
		{
			get
			{
				if (!_capturingKey)
				{
					return _keyCapturedFrame == Time.frameCount;
				}
				return true;
			}
		}

		public SearchPanel(GuideLines lines)
		{
			_lines = lines;
		}

		public void Open()
		{
			if (!((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)GUIManager.CustomGUIFront == (Object)null))
			{
				_lines.Clear();
				if ((Object)(object)_root == (Object)null)
				{
					Build();
				}
				_root.SetActive(true);
				ShowSettings(show: false);
				_open = true;
				GUIManager.BlockInput(true);
				_selectedToken = null;
				Rescan();
				SetQuery("");
				RefreshResults();
				FocusQuery();
			}
		}

		public void Close()
		{
			if (_open)
			{
				_open = false;
				_capturingKey = false;
				_snapshot = null;
				if ((Object)(object)_root != (Object)null)
				{
					_root.SetActive(false);
				}
				GUIManager.BlockInput(false);
			}
		}

		public void Update()
		{
			if (!_open)
			{
				return;
			}
			if ((Object)(object)_root == (Object)null)
			{
				Close();
			}
			else if (_capturingKey)
			{
				CaptureKey();
			}
			else if (Input.GetKeyDown((KeyCode)27))
			{
				if (_settingsView.activeSelf)
				{
					ShowSettings(show: false);
				}
				else
				{
					Close();
				}
			}
			else if (_searchView.activeSelf && (Input.GetKeyDown((KeyCode)13) || Input.GetKeyDown((KeyCode)271)))
			{
				DoSearch();
			}
		}

		private void Rescan()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			_snapshot = (((Object)(object)localPlayer != (Object)null) ? ContainerScanner.Scan(((Component)localPlayer).transform.position, Plugin.SearchRadius.Value) : new ScanResult());
		}

		private void RefreshResults()
		{
			if (_snapshot != null)
			{
				List<ItemEntry> list = _snapshot.Filter(_query.text);
				for (int i = 0; i < _rows.Count; i++)
				{
					_rows[i].Bind((i < list.Count) ? list[i] : null);
				}
				float value = Plugin.SearchRadius.Value;
				if (_snapshot.ContainerCount == 0)
				{
					_status.text = $"No chests within {value:0} m.";
				}
				else if (list.Count == 0)
				{
					_status.text = "No matching items in nearby chests.";
				}
				else if (list.Count > 9)
				{
					_status.text = $"…and {list.Count - 9} more. Keep typing to narrow down.";
				}
				else
				{
					_status.text = $"{_snapshot.ContainerCount} chest(s) within {value:0} m.";
				}
			}
		}

		private void DoSearch()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			string text = _query.text.Trim();
			if (text.Length == 0)
			{
				_status.text = "Type an item name first.";
				return;
			}
			ScanResult scanResult = ContainerScanner.Scan(((Component)localPlayer).transform.position, Plugin.SearchRadius.Value);
			List<ItemEntry> list = scanResult.Resolve(text, _selectedToken);
			List<Container> list2 = list.SelectMany((ItemEntry e) => e.Containers).Distinct().ToList();
			if (list2.Count == 0)
			{
				_snapshot = scanResult;
				RefreshResults();
				_status.text = $"No chest within {Plugin.SearchRadius.Value:0} m contains \"{text}\".";
				return;
			}
			_lines.Show(list2);
			Close();
			string text2 = ((list.Count == 1) ? list[0].DisplayName : ("\"" + text + "\""));
			int num = list.Sum((ItemEntry e) => e.Total);
			((Character)localPlayer).Message((MessageType)2, string.Format("{0} x{1} in {2} chest{3}", text2, num, list2.Count, (list2.Count == 1) ? "" : "s"), 0, (Sprite)null, false);
		}

		private void Cancel()
		{
			_lines.Clear();
			Close();
		}

		private void SelectEntry(ItemEntry entry)
		{
			if (entry != null)
			{
				SetQuery(entry.DisplayName);
				_selectedToken = entry.Token;
				DoSearch();
			}
		}

		private void OnQueryChanged(string _)
		{
			if (!_suppressQueryChange)
			{
				_selectedToken = null;
				RefreshResults();
			}
		}

		private void SetQuery(string text)
		{
			_suppressQueryChange = true;
			_query.text = text;
			_suppressQueryChange = false;
		}

		private void FocusQuery()
		{
			((Selectable)_query).Select();
			_query.ActivateInputField();
		}

		private void ShowSettings(bool show)
		{
			_searchView.SetActive(!show);
			_settingsView.SetActive(show);
			SetButtonText(_settingsButton, show ? "Back" : "Settings");
			if (show)
			{
				_radiusField.text = Plugin.SearchRadius.Value.ToString("0");
				UpdateKeyButton();
			}
			else if (_open)
			{
				Rescan();
				RefreshResults();
				FocusQuery();
			}
		}

		private void SetRadius(float value)
		{
			Plugin.SearchRadius.Value = Mathf.Clamp(Mathf.Round(value), 5f, 100f);
			_radiusField.text = Plugin.SearchRadius.Value.ToString("0");
		}

		private void OnRadiusEdited(string text)
		{
			if (float.TryParse(text, out var result))
			{
				SetRadius(result);
			}
			else
			{
				_radiusField.text = Plugin.SearchRadius.Value.ToString("0");
			}
		}

		private void BeginKeyCapture()
		{
			_capturingKey = true;
			SetButtonText(_keyButton, "Press a key…");
		}

		private void CaptureKey()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0036: 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)
			if (!Input.anyKeyDown)
			{
				return;
			}
			KeyCode[] allKeys = AllKeys;
			foreach (KeyCode val in allKeys)
			{
				if (!Input.GetKeyDown(val))
				{
					continue;
				}
				if ((int)val != 27)
				{
					if (Input.inputString.Length > 0)
					{
						break;
					}
					Plugin.SearchKey.Value = new KeyboardShortcut(val, Array.Empty<KeyCode>());
				}
				_capturingKey = false;
				_keyCapturedFrame = Time.frameCount;
				UpdateKeyButton();
				break;
			}
		}

		private void UpdateKeyButton()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			SetButtonText(_keyButton, ((object)Plugin.SearchKey.Value/*cast due to .constrained prefix*/).ToString());
		}

		private void Build()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			GUIManager instance = GUIManager.Instance;
			_rows.Clear();
			_root = instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 440f, 580f, true);
			((Object)_root).name = "ItemSearch_Panel";
			MakeText("Item Search", _root.transform, new Vector2(-60f, -32f), 240f, 40f, 26, (TextAnchor)3, TextColor);
			_settingsButton = MakeButton("Settings", _root.transform, new Vector2(140f, -32f), 110f, 34f, (UnityAction)delegate
			{
				ShowSettings(!_settingsView.activeSelf);
			});
			BuildSearchView();
			BuildSettingsView();
			_root.SetActive(false);
		}

		private void BuildSearchView()
		{
			//IL_0033: 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_00cb: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			//IL_0146: 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_0166: Expected O, but got Unknown
			_searchView = MakeContainer("SearchView", _root.transform);
			Transform transform = _searchView.transform;
			_query = MakeInput(transform, new Vector2(0f, -80f), 400f, 38f, "Item name…", (ContentType)0, 64);
			((UnityEvent<string>)(object)_query.onValueChanged).AddListener((UnityAction<string>)OnQueryChanged);
			for (int i = 0; i < 9; i++)
			{
				_rows.Add(new Row(transform, -128f - (float)i * 38f, SelectEntry));
			}
			_status = MakeText("", transform, new Vector2(0f, -464f), 400f, 26f, 15, (TextAnchor)4, DimText);
			float num = -538f;
			MakeButton("Search", transform, new Vector2(-135f, num), 120f, 40f, new UnityAction(DoSearch));
			MakeButton("Cancel", transform, new Vector2(0f, num), 120f, 40f, new UnityAction(Cancel));
			MakeButton("Close", transform, new Vector2(135f, num), 120f, 40f, new UnityAction(Close));
		}

		private void BuildSettingsView()
		{
			//IL_0037: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_00fd: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: 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_015c: Expected O, but got Unknown
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			_settingsView = MakeContainer("SettingsView", _root.transform);
			Transform transform = _settingsView.transform;
			MakeText("Search radius (m)", transform, new Vector2(-95f, -100f), 200f, 34f, 18, (TextAnchor)3, TextColor);
			MakeButton("-", transform, new Vector2(55f, -100f), 40f, 34f, (UnityAction)delegate
			{
				SetRadius(Plugin.SearchRadius.Value - 5f);
			});
			_radiusField = MakeInput(transform, new Vector2(115f, -100f), 70f, 34f, "50", (ContentType)2, 3);
			((UnityEvent<string>)(object)_radiusField.onEndEdit).AddListener((UnityAction<string>)OnRadiusEdited);
			MakeButton("+", transform, new Vector2(175f, -100f), 40f, 34f, (UnityAction)delegate
			{
				SetRadius(Plugin.SearchRadius.Value + 5f);
			});
			MakeText("Search key", transform, new Vector2(-95f, -180f), 200f, 34f, 18, (TextAnchor)3, TextColor);
			_keyButton = MakeButton("F3", transform, new Vector2(115f, -180f), 160f, 34f, new UnityAction(BeginKeyCapture));
			MakeText("Click, then press a non-typing key (F-keys etc.). Esc cancels.", transform, new Vector2(0f, -220f), 400f, 24f, 14, (TextAnchor)4, DimText);
		}

		private static GameObject MakeContainer(string name, Transform parent)
		{
			//IL_0014: 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_0026: 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_0032: 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_003d: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.offsetMin = Vector2.zero;
			val2.offsetMax = Vector2.zero;
			return val;
		}

		private static Text MakeText(string text, Transform parent, Vector2 pos, float width, float height, int size, TextAnchor align, Color color)
		{
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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)
			Text component = GUIManager.Instance.CreateText(text, parent, TopCenter, TopCenter, pos, GUIManager.Instance.AveriaSerifBold, size, color, true, Color.black, width, height, false).GetComponent<Text>();
			component.alignment = align;
			((Graphic)component).raycastTarget = false;
			component.horizontalOverflow = (HorizontalWrapMode)0;
			component.verticalOverflow = (VerticalWrapMode)0;
			return component;
		}

		private static GameObject MakeButton(string text, Transform parent, Vector2 pos, float width, float height, UnityAction onClick)
		{
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GUIManager.Instance.CreateButton(text, parent, TopCenter, TopCenter, pos, width, height);
			obj.GetComponent<ButtonSfx>().m_selectSfxPrefab = null;
			((UnityEvent)obj.GetComponent<Button>().onClick).AddListener(onClick);
			return obj;
		}

		private static InputField MakeInput(Transform parent, Vector2 pos, float width, float height, string placeholder, ContentType type, int limit)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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)
			InputField component = GUIManager.Instance.CreateInputField(parent, TopCenter, TopCenter, pos, type, placeholder, 18, width, height).GetComponent<InputField>();
			component.characterLimit = limit;
			return component;
		}

		private static void SetButtonText(GameObject button, string text)
		{
			button.GetComponentInChildren<Text>(true).text = text;
		}
	}
}