Decompiled source of ChestSearch v1.0.6

plugins/ChestSearch/ChestSearch.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[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("ChestSearch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f9b163275ab4d47a7afb50ff89f586c3a2035d9b")]
[assembly: AssemblyProduct("ChestSearch")]
[assembly: AssemblyTitle("ChestSearch")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace ChestSearch;

[HarmonyPatch(typeof(Player), "SetSelectedPiece", new Type[] { typeof(Vector2Int) })]
public static class BuildPullPatch
{
	[DllImport("user32.dll")]
	private static extern short GetAsyncKeyState(int vKey);

	private static bool IsOSKeyDown(int vKey)
	{
		return (GetAsyncKeyState(vKey) & 0x8000) != 0;
	}

	private static void Postfix(Player __instance, Vector2Int p)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		int value = Plugin.BuildPullVKey.Value;
		if (value == 0 || !IsOSKeyDown(value) || (Object)(object)__instance == (Object)null)
		{
			return;
		}
		Piece piece = __instance.GetPiece(p);
		if ((Object)(object)piece == (Object)null || piece.m_resources == null)
		{
			return;
		}
		Inventory inventory = ((Humanoid)__instance).GetInventory();
		if (inventory == null)
		{
			return;
		}
		float value2 = Plugin.TakeRange.Value;
		List<string> list = new List<string>();
		List<string> list2 = new List<string>();
		Requirement[] resources = piece.m_resources;
		foreach (Requirement val in resources)
		{
			if ((Object)(object)val.m_resItem == (Object)null || val.m_amount <= 0)
			{
				continue;
			}
			string name = val.m_resItem.m_itemData.m_shared.m_name;
			string arg = Localization.instance.Localize(name);
			int num = inventory.CountItems(name, -1, true);
			int num2 = val.m_amount - num;
			if (num2 > 0)
			{
				int num3 = ContainerSearcher.TakeItems(name, num2, value2);
				if (num3 >= num2)
				{
					list.Add($"{num3}x {arg}");
				}
				else if (num3 > 0)
				{
					list.Add($"{num3}x {arg}");
					list2.Add($"{num2 - num3}x {arg}");
				}
				else
				{
					list2.Add($"{num2}x {arg}");
				}
			}
		}
		if (list.Count > 0)
		{
			string text = "Pulled " + string.Join(", ", list);
			if (list2.Count > 0)
			{
				text = text + "  |  Missing " + string.Join(", ", list2);
			}
			MessageHud instance = MessageHud.instance;
			if (instance != null)
			{
				instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false);
			}
		}
		else if (list2.Count > 0)
		{
			MessageHud instance2 = MessageHud.instance;
			if (instance2 != null)
			{
				instance2.ShowMessage((MessageType)1, "Missing " + string.Join(", ", list2), 0, (Sprite)null, false);
			}
		}
	}
}
public class ContainerHighlight : MonoBehaviour
{
	private float duration = 8f;

	private float elapsed;

	private readonly List<Light> lights = new List<Light>();

	private readonly List<float> offsets = new List<float>();

	private const int LightCount = 3;

	private const float OrbitRadius = 1.2f;

	private const float OrbitSpeed = 2f;

	private const float BobSpeed = 3f;

	private const float BobAmount = 0.3f;

	private float baseY;

	private ParticleSystem particles;

	private static readonly Color highlightColor = new Color(0.4f, 0.8f, 1f, 1f);

	private readonly List<Renderer> glowRenderers = new List<Renderer>();

	private readonly List<Color> originalColors = new List<Color>();

	private static readonly int EmissionColor = Shader.PropertyToID("_EmissionColor");

	public static void Highlight(Container container, float seconds = 8f)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: 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_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)container == (Object)null))
		{
			ContainerHighlight componentInChildren = ((Component)container).GetComponentInChildren<ContainerHighlight>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)componentInChildren).gameObject);
			}
			GameObject val = new GameObject("ChestSearchHighlight");
			val.transform.SetParent(((Component)container).transform, false);
			val.transform.localPosition = Vector3.up * 1.2f;
			val.AddComponent<ContainerHighlight>().duration = seconds;
		}
	}

	private void Start()
	{
		//IL_0007: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: 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_0153: Expected O, but got Unknown
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: 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_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: 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)
		//IL_01fe: 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_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_023c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0246: Unknown result type (might be due to invalid IL or missing references)
		//IL_024d: Expected O, but got Unknown
		//IL_0257: Unknown result type (might be due to invalid IL or missing references)
		//IL_0261: Unknown result type (might be due to invalid IL or missing references)
		//IL_0266: Unknown result type (might be due to invalid IL or missing references)
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_027c: 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_028d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d5: 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_02e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0327: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Unknown result type (might be due to invalid IL or missing references)
		//IL_036c: Expected O, but got Unknown
		//IL_0371: 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)
		baseY = ((Component)this).transform.localPosition.y;
		Container componentInParent = ((Component)this).GetComponentInParent<Container>();
		if ((Object)(object)componentInParent != (Object)null)
		{
			Renderer[] componentsInChildren = ((Component)componentInParent).GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				Material[] materials = val.materials;
				foreach (Material val2 in materials)
				{
					if (val2.HasProperty(EmissionColor))
					{
						glowRenderers.Add(val);
						originalColors.Add(val2.GetColor(EmissionColor));
						val2.EnableKeyword("_EMISSION");
						break;
					}
				}
			}
		}
		for (int k = 0; k < 3; k++)
		{
			GameObject val3 = new GameObject($"OrbitLight_{k}");
			val3.transform.SetParent(((Component)this).transform, false);
			Light val4 = val3.AddComponent<Light>();
			val4.type = (LightType)2;
			val4.color = highlightColor;
			val4.intensity = 1.5f;
			val4.range = 3f;
			val4.shadows = (LightShadows)0;
			lights.Add(val4);
			offsets.Add((float)k * 120f);
		}
		GameObject val5 = new GameObject("Sparkles");
		val5.transform.SetParent(((Component)this).transform, false);
		val5.transform.localPosition = Vector3.zero;
		particles = val5.AddComponent<ParticleSystem>();
		MainModule main = particles.main;
		((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(1f);
		((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.5f);
		((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.08f);
		((MainModule)(ref main)).maxParticles = 30;
		((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
		((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(highlightColor);
		((MainModule)(ref main)).gravityModifier = MinMaxCurve.op_Implicit(-0.1f);
		EmissionModule emission = particles.emission;
		((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(12f);
		ShapeModule shape = particles.shape;
		((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0;
		((ShapeModule)(ref shape)).radius = 0.6f;
		ColorOverLifetimeModule colorOverLifetime = particles.colorOverLifetime;
		((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled = true;
		Gradient val6 = new Gradient();
		val6.SetKeys((GradientColorKey[])(object)new GradientColorKey[3]
		{
			new GradientColorKey(highlightColor, 0f),
			new GradientColorKey(highlightColor, 0.5f),
			new GradientColorKey(highlightColor, 1f)
		}, (GradientAlphaKey[])(object)new GradientAlphaKey[3]
		{
			new GradientAlphaKey(0f, 0f),
			new GradientAlphaKey(1f, 0.2f),
			new GradientAlphaKey(0f, 1f)
		});
		((ColorOverLifetimeModule)(ref colorOverLifetime)).color = new MinMaxGradient(val6);
		SizeOverLifetimeModule sizeOverLifetime = particles.sizeOverLifetime;
		((SizeOverLifetimeModule)(ref sizeOverLifetime)).enabled = true;
		((SizeOverLifetimeModule)(ref sizeOverLifetime)).size = new MinMaxCurve(1f, AnimationCurve.Linear(0f, 1f, 1f, 0f));
		ParticleSystemRenderer component = val5.GetComponent<ParticleSystemRenderer>();
		Shader val7 = Shader.Find("Legacy Shaders/Particles/Additive") ?? Shader.Find("Particles/Additive") ?? Shader.Find("Sprites/Default");
		((Renderer)component).material = new Material(val7);
		((Renderer)component).material.color = highlightColor;
	}

	private void Update()
	{
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		elapsed += Time.deltaTime;
		float num = 1f;
		if (elapsed > duration - 2f)
		{
			num = Mathf.Clamp01((duration - elapsed) / 2f);
		}
		for (int i = 0; i < lights.Count; i++)
		{
			float num2 = (Time.time * 2f * 360f + offsets[i]) * ((float)Math.PI / 180f);
			float num3 = Mathf.Cos(num2) * 1.2f;
			float num4 = Mathf.Sin(num2) * 1.2f;
			float num5 = Mathf.Sin(Time.time * 3f + offsets[i] * ((float)Math.PI / 180f)) * 0.3f;
			((Component)lights[i]).transform.localPosition = new Vector3(num3, num5, num4);
			lights[i].intensity = 1.5f * num;
		}
		if ((Object)(object)particles != (Object)null)
		{
			EmissionModule emission = particles.emission;
			((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(12f * num);
		}
		float num6 = (Mathf.Sin(Time.time * 3f) * 0.5f + 0.5f) * num;
		for (int j = 0; j < glowRenderers.Count; j++)
		{
			if (!((Object)(object)glowRenderers[j] != (Object)null))
			{
				continue;
			}
			Material[] materials = glowRenderers[j].materials;
			foreach (Material val in materials)
			{
				if (val.HasProperty(EmissionColor))
				{
					val.SetColor(EmissionColor, highlightColor * num6 * 2f);
				}
			}
		}
		if (elapsed >= duration)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}

	private void OnDestroy()
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < glowRenderers.Count; i++)
		{
			if (!((Object)(object)glowRenderers[i] != (Object)null))
			{
				continue;
			}
			Material[] materials = glowRenderers[i].materials;
			foreach (Material val in materials)
			{
				if (val.HasProperty(EmissionColor))
				{
					val.SetColor(EmissionColor, originalColors[i]);
				}
			}
		}
		foreach (Light light in lights)
		{
			if ((Object)(object)light != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)light).gameObject);
			}
		}
	}
}
public struct SearchResult
{
	public string ContainerName;

	public Vector3 Position;

	public float Distance;

	public List<ItemMatch> Items;

	public Container Container;
}
public struct ItemMatch
{
	public string Name;

	public int Stack;

	public string QualityText;

	public string ItemKey;
}
public static class ContainerSearcher
{
	public static List<SearchResult> Search(string query)
	{
		//IL_0027: 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_0062: 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_0210: 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)
		List<SearchResult> list = new List<SearchResult>();
		if (string.IsNullOrWhiteSpace(query) || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			return list;
		}
		Vector3 position = ((Component)Player.m_localPlayer).transform.position;
		string value = query.ToLowerInvariant();
		Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
		foreach (Container val in array)
		{
			if ((Object)(object)val == (Object)null || val.GetInventory() == null)
			{
				continue;
			}
			float distance = Vector3.Distance(position, ((Component)val).transform.position);
			List<ItemData> allItems = val.GetInventory().GetAllItems();
			if (allItems == null || allItems.Count == 0)
			{
				continue;
			}
			List<ItemMatch> list2 = new List<ItemMatch>();
			foreach (ItemData item in allItems)
			{
				string text = Localization.instance.Localize(item.m_shared.m_name);
				if (text.ToLowerInvariant().Contains(value))
				{
					string qualityText = ((item.m_shared.m_maxQuality > 1) ? $" (Lv {item.m_quality})" : "");
					list2.Add(new ItemMatch
					{
						Name = text,
						Stack = item.m_stack,
						QualityText = qualityText,
						ItemKey = item.m_shared.m_name
					});
				}
			}
			if (list2.Count <= 0)
			{
				continue;
			}
			List<ItemMatch> items = (from m in (from m in list2
					group m by m.Name + m.QualityText).Select(delegate(IGrouping<string, ItemMatch> g)
				{
					ItemMatch result = default(ItemMatch);
					result.Name = g.First().Name;
					result.Stack = g.Sum((ItemMatch m) => m.Stack);
					result.QualityText = g.First().QualityText;
					result.ItemKey = g.First().ItemKey;
					return result;
				})
				orderby m.Name
				select m).ToList();
			string containerName = GetContainerName(val);
			list.Add(new SearchResult
			{
				ContainerName = containerName,
				Position = ((Component)val).transform.position,
				Distance = distance,
				Items = items,
				Container = val
			});
		}
		return list.OrderBy((SearchResult r) => r.Distance).ToList();
	}

	private static string GetContainerName(Container container)
	{
		Piece componentInParent = ((Component)container).GetComponentInParent<Piece>();
		if ((Object)(object)componentInParent != (Object)null)
		{
			string text = Localization.instance.Localize(componentInParent.m_name);
			if (!string.IsNullOrEmpty(text))
			{
				return text;
			}
		}
		if (!string.IsNullOrEmpty(container.m_name))
		{
			return Localization.instance.Localize(container.m_name);
		}
		return ((Object)((Component)container).gameObject).name.Replace("(Clone)", "").Trim();
	}

	public static void PingContainer(Container container)
	{
		//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_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_0042: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)container == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null))
		{
			ContainerHighlight.Highlight(container);
			Vector3 val = ((Component)container).transform.position + Vector3.up;
			Chat instance = Chat.instance;
			if (instance != null)
			{
				instance.SendPing(val);
			}
		}
	}

	public static int TakeItems(Container container, string itemKey, float maxRange)
	{
		//IL_0022: 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)
		if ((Object)(object)container == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			return 0;
		}
		if (Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)container).transform.position) > maxRange)
		{
			return 0;
		}
		ZNetView component = ((Component)container).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && !component.IsOwner())
		{
			component.ClaimOwnership();
		}
		Inventory inventory = container.GetInventory();
		Inventory inventory2 = ((Humanoid)Player.m_localPlayer).GetInventory();
		if (inventory == null || inventory2 == null)
		{
			return 0;
		}
		int num = 0;
		List<ItemData> allItems = inventory.GetAllItems();
		for (int num2 = allItems.Count - 1; num2 >= 0; num2--)
		{
			ItemData val = allItems[num2];
			if (!(val.m_shared.m_name != itemKey))
			{
				if (!inventory2.CanAddItem(val, -1))
				{
					break;
				}
				int stack = val.m_stack;
				if (inventory2.AddItem(val))
				{
					inventory.RemoveItem(val);
					num += stack;
				}
			}
		}
		return num;
	}

	public static int TakeItems(string itemKey, int maxCount, float maxRange)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: 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_0054: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Player.m_localPlayer == (Object)null || maxCount <= 0)
		{
			return 0;
		}
		Vector3 position = ((Component)Player.m_localPlayer).transform.position;
		Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
		int num = 0;
		Container[] array2 = array;
		foreach (Container val in array2)
		{
			if (num >= maxCount)
			{
				break;
			}
			if (!((Object)(object)val == (Object)null) && val.GetInventory() != null && !(Vector3.Distance(position, ((Component)val).transform.position) > maxRange))
			{
				int maxCount2 = maxCount - num;
				int num2 = TakeItemsFromContainer(val, itemKey, maxCount2);
				num += num2;
			}
		}
		return num;
	}

	private static int TakeItemsFromContainer(Container container, string itemKey, int maxCount)
	{
		ZNetView component = ((Component)container).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && !component.IsOwner())
		{
			component.ClaimOwnership();
		}
		Inventory inventory = container.GetInventory();
		Inventory inventory2 = ((Humanoid)Player.m_localPlayer).GetInventory();
		if (inventory == null || inventory2 == null)
		{
			return 0;
		}
		int num = 0;
		List<ItemData> allItems = inventory.GetAllItems();
		int num2 = allItems.Count - 1;
		while (num2 >= 0 && num < maxCount)
		{
			ItemData val = allItems[num2];
			if (!(val.m_shared.m_name != itemKey))
			{
				int num3 = maxCount - num;
				int num4 = Mathf.Min(val.m_stack, num3);
				if (num4 >= val.m_stack)
				{
					if (!inventory2.CanAddItem(val, -1))
					{
						break;
					}
					if (inventory2.AddItem(val))
					{
						inventory.RemoveItem(val);
						num += num4;
					}
				}
				else
				{
					ItemData val2 = val.Clone();
					val2.m_stack = num4;
					if (!inventory2.CanAddItem(val2, -1))
					{
						break;
					}
					if (inventory2.AddItem(val2))
					{
						val.m_stack -= num4;
						num += num4;
					}
				}
			}
			num2--;
		}
		return num;
	}
}
public enum TidyCategory
{
	Material,
	Consumable,
	OneHandedWeapon,
	TwoHandedWeapon,
	TwoHandedWeaponLeft,
	Bow,
	Shield,
	Helmet,
	Chest,
	Legs,
	Hands,
	Shoulder,
	Tool,
	Torch,
	Utility,
	Trinket,
	Ammo,
	AmmoNonEquipable,
	Trophy,
	Fish,
	Customization,
	Misc
}
public class PlannedSlot
{
	public Container TargetContainer;

	public int TargetContainerIdx;

	public Vector2i TargetPos;

	public ItemData Item;

	public Container CurrentContainer;

	public bool Done;
}
public static class ContainerTidy
{
	private static List<string> logLines;

	private static MethodInfo inventoryChangedMethod;

	private static void LogLine(string msg)
	{
		logLines?.Add(msg);
	}

	private static void FlushLog()
	{
		if (logLines == null || logLines.Count == 0)
		{
			return;
		}
		try
		{
			File.WriteAllLines(Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location) ?? ".", "tidy-debug.log"), logLines);
		}
		catch
		{
		}
	}

	private static void InvokeChanged(Inventory inv)
	{
		if (inventoryChangedMethod == null)
		{
			inventoryChangedMethod = typeof(Inventory).GetMethod("Changed", BindingFlags.Instance | BindingFlags.NonPublic);
		}
		inventoryChangedMethod?.Invoke(inv, null);
	}

	public static TidyCategory GetCategory(ItemType type)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Expected I4, but got Unknown
		return (type - 1) switch
		{
			0 => TidyCategory.Material, 
			1 => TidyCategory.Consumable, 
			2 => TidyCategory.OneHandedWeapon, 
			13 => TidyCategory.TwoHandedWeapon, 
			21 => TidyCategory.TwoHandedWeaponLeft, 
			3 => TidyCategory.Bow, 
			4 => TidyCategory.Shield, 
			5 => TidyCategory.Helmet, 
			6 => TidyCategory.Chest, 
			10 => TidyCategory.Legs, 
			11 => TidyCategory.Hands, 
			16 => TidyCategory.Shoulder, 
			18 => TidyCategory.Tool, 
			14 => TidyCategory.Torch, 
			17 => TidyCategory.Utility, 
			23 => TidyCategory.Trinket, 
			8 => TidyCategory.Ammo, 
			22 => TidyCategory.AmmoNonEquipable, 
			12 => TidyCategory.Trophy, 
			20 => TidyCategory.Fish, 
			9 => TidyCategory.Customization, 
			_ => TidyCategory.Misc, 
		};
	}

	private static int CompareItems(ItemData a, ItemData b)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		TidyCategory category = GetCategory(a.m_shared.m_itemType);
		TidyCategory category2 = GetCategory(b.m_shared.m_itemType);
		if (category != category2)
		{
			return category.CompareTo(category2);
		}
		int num = string.Compare(a.m_shared.m_name, b.m_shared.m_name, StringComparison.Ordinal);
		if (num != 0)
		{
			return num;
		}
		return b.m_stack.CompareTo(a.m_stack);
	}

	private static int CompareItemsStable((Container c, ItemData item) a, (Container c, ItemData item) b, List<Container> containers)
	{
		int num = CompareItems(a.item, b.item);
		if (num != 0)
		{
			return num;
		}
		int num2 = containers.IndexOf(a.c);
		int num3 = containers.IndexOf(b.c);
		if (num2 != num3)
		{
			return num2.CompareTo(num3);
		}
		int num4 = a.item.m_gridPos.y * 100 + a.item.m_gridPos.x;
		int value = b.item.m_gridPos.y * 100 + b.item.m_gridPos.x;
		return num4.CompareTo(value);
	}

	private static string ItemKey(ItemData item)
	{
		return $"{item.m_shared.m_name}|{item.m_quality}|{item.m_worldLevel}";
	}

	private static string DisplayName(ItemData item)
	{
		return Localization.instance.Localize(item.m_shared.m_name);
	}

	public static string Tidy(float range)
	{
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_045f: Unknown result type (might be due to invalid IL or missing references)
		//IL_053b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0540: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			return "No player";
		}
		List<Container> containers = GetNearbyContainers(range);
		if (containers.Count < 2)
		{
			return "Need at least 2 containers nearby";
		}
		foreach (Container item4 in containers)
		{
			ZNetView component = ((Component)item4).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && !component.IsOwner())
			{
				component.ClaimOwnership();
			}
		}
		logLines = new List<string>();
		LogLine($"=== TIDY START === {containers.Count} containers");
		SortContainersByLayout(containers);
		LogLine("\n--- CONTAINERS (spatial order) ---");
		int num = 0;
		for (int j = 0; j < containers.Count; j++)
		{
			Container val = containers[j];
			Inventory inventory = val.GetInventory();
			Vector3 position = ((Component)val).transform.position;
			int num2 = inventory.GetWidth() * inventory.GetHeight();
			num += num2;
			LogLine($"  [{j}] {((Object)((Component)val).gameObject).name} ({position.x:F1},{position.y:F1},{position.z:F1}) {inventory.GetWidth()}x{inventory.GetHeight()}={num2} items:{inventory.NrOfItems()}");
		}
		LogLine("\n--- PHASE 1: In-place stack consolidation ---");
		int num3 = 0;
		foreach (Container item5 in containers)
		{
			int num4 = ConsolidateWithinContainer(item5);
			num3 += num4;
			if (num4 > 0)
			{
				LogLine($"  {((Object)((Component)item5).gameObject).name}: merged {num4} stacks");
			}
		}
		LogLine("\n--- PHASE 2: Cross-container consolidation ---");
		num3 += ConsolidateAcrossContainers(containers);
		LogLine("\n--- BUILDING TARGET PLAN ---");
		List<(Container, ItemData)> list = new List<(Container, ItemData)>();
		LogLine("\n--- CURRENT STATE (before plan) ---");
		for (int k = 0; k < containers.Count; k++)
		{
			Container val2 = containers[k];
			List<ItemData> allItems = val2.GetInventory().GetAllItems();
			if (allItems.Count == 0)
			{
				continue;
			}
			LogLine($"  Container[{k}] ({allItems.Count} items):");
			foreach (ItemData item6 in allItems)
			{
				list.Add((val2, item6));
				LogLine($"    ({item6.m_gridPos.x},{item6.m_gridPos.y}) {DisplayName(item6)} x{item6.m_stack} hash:{((object)item6).GetHashCode()}");
			}
		}
		list.Sort(((Container c, ItemData item) a, (Container c, ItemData item) b) => CompareItemsStable(a, b, containers));
		HashSet<TidyCategory> hashSet = new HashSet<TidyCategory>();
		foreach (var item7 in list)
		{
			ItemData item = item7.Item2;
			hashSet.Add(GetCategory(item.m_shared.m_itemType));
		}
		int count = list.Count;
		if (count > num)
		{
			int num5 = count - num;
			LogLine($"ABORT: {count} slots needed but only {num} available");
			FlushLog();
			return $"Need {num5} more slots to tidy ({count} stacks, {num} slots available)";
		}
		List<PlannedSlot> list2 = new List<PlannedSlot>();
		int num6 = 0;
		int num7 = 0;
		int num8 = 0;
		TidyCategory? tidyCategory = null;
		for (int l = 0; l < list.Count; l++)
		{
			(Container, ItemData) tuple = list[l];
			Container item2 = tuple.Item1;
			ItemData item3 = tuple.Item2;
			TidyCategory category = GetCategory(item3.m_shared.m_itemType);
			if (tidyCategory.HasValue && tidyCategory.Value != category && num7 + num8 > 0)
			{
				num6 = Mathf.Min(num6 + 1, containers.Count - 1);
				num7 = 0;
				num8 = 0;
			}
			tidyCategory = category;
			Inventory inventory2 = containers[num6].GetInventory();
			int width = inventory2.GetWidth();
			int height = inventory2.GetHeight();
			if (num8 >= height)
			{
				num6 = Mathf.Min(num6 + 1, containers.Count - 1);
				num7 = 0;
				num8 = 0;
				Inventory inventory3 = containers[num6].GetInventory();
				width = inventory3.GetWidth();
				height = inventory3.GetHeight();
			}
			list2.Add(new PlannedSlot
			{
				TargetContainer = containers[num6],
				TargetContainerIdx = num6,
				TargetPos = new Vector2i(num7, num8),
				Item = item3,
				CurrentContainer = item2,
				Done = ((Object)(object)item2 == (Object)(object)containers[num6])
			});
			num7++;
			if (num7 >= width)
			{
				num7 = 0;
				num8++;
			}
		}
		LogLine($"\nPlan: {list2.Count} items across {containers.Count} containers");
		int num9 = list2.Count((PlannedSlot p) => p.Done && (Object)(object)p.CurrentContainer == (Object)(object)p.TargetContainer);
		int num10 = list2.Count - num9;
		LogLine($"  Already in correct container: {num9}");
		LogLine($"  Need to move: {num10}");
		LogLine("\n--- TARGET PLAN ---");
		foreach (PlannedSlot item8 in list2)
		{
			int num11 = -1;
			for (int m = 0; m < containers.Count; m++)
			{
				if ((Object)(object)containers[m] == (Object)(object)item8.CurrentContainer)
				{
					num11 = m;
					break;
				}
			}
			string text = (((Object)(object)item8.CurrentContainer == (Object)(object)item8.TargetContainer) ? "OK" : "MOVE");
			bool flag = (Object)(object)item8.CurrentContainer == (Object)(object)item8.TargetContainer;
			LogLine($"  Container[{item8.TargetContainerIdx}] ({item8.TargetPos.x},{item8.TargetPos.y}): {DisplayName(item8.Item)} x{item8.Item.m_stack} [{text}] currentlyIn:Container[{num11}] gridPos:({item8.Item.m_gridPos.x},{item8.Item.m_gridPos.y}) refMatch:{flag} hash:{((object)item8.Item).GetHashCode()}");
		}
		LogLine("\n--- PHASE 3: Executing moves ---");
		int num12 = ExecutePlan(list2, containers);
		foreach (Container item9 in containers)
		{
			InvokeChanged(item9.GetInventory());
		}
		LogLine("\n--- FINAL STATE (after all moves + gridPos) ---");
		for (int n = 0; n < containers.Count; n++)
		{
			List<ItemData> allItems2 = containers[n].GetInventory().GetAllItems();
			if (allItems2.Count == 0)
			{
				continue;
			}
			LogLine($"  Container[{n}] ({allItems2.Count} items):");
			foreach (ItemData item10 in allItems2)
			{
				LogLine($"    ({item10.m_gridPos.x},{item10.m_gridPos.y}) {DisplayName(item10)} x{item10.m_stack} hash:{((object)item10).GetHashCode()}");
			}
		}
		LogLine("\n--- VALIDATION ---");
		string text2 = null;
		HashSet<string> hashSet2 = new HashSet<string>();
		int num13 = 0;
		for (int num14 = 0; num14 < containers.Count; num14++)
		{
			foreach (ItemData item11 in (from i in containers[num14].GetInventory().GetAllItems()
				orderby i.m_gridPos.y, i.m_gridPos.x
				select i).ToList())
			{
				string name = item11.m_shared.m_name;
				if (name != text2)
				{
					if (hashSet2.Contains(name))
					{
						LogLine($"  VIOLATION: {DisplayName(item11)} appears again in Container[{num14}] after gap! (last seen earlier)");
						num13++;
					}
					if (text2 != null)
					{
						hashSet2.Add(text2);
					}
					text2 = name;
				}
			}
		}
		if (num13 == 0)
		{
			LogLine("  All items contiguous — PASS");
		}
		else
		{
			LogLine($"  {num13} contiguity violations found");
		}
		List<string> list3 = new List<string>();
		if (num3 > 0)
		{
			list3.Add($"consolidated {num3} stacks");
		}
		if (num12 > 0)
		{
			list3.Add($"moved {num12} items");
		}
		if (num3 == 0 && num12 == 0)
		{
			FlushLog();
			return "Already tidy!";
		}
		string text3 = "Tidied: " + string.Join(", ", list3);
		LogLine("\n=== RESULT: " + text3 + " ===");
		FlushLog();
		return text3;
	}

	private static int ExecutePlan(List<PlannedSlot> plan, List<Container> containers)
	{
		//IL_04cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory();
		for (int i = 0; i < plan.Count; i++)
		{
			PlannedSlot p = plan[i];
			if ((Object)(object)p.CurrentContainer == (Object)(object)p.TargetContainer)
			{
				p.Done = true;
				continue;
			}
			Inventory inventory2 = p.TargetContainer.GetInventory();
			Inventory val = (((Object)(object)p.CurrentContainer != (Object)null) ? p.CurrentContainer.GetInventory() : inventory);
			if (!inventory2.CanAddItem(p.Item, -1))
			{
				bool flag = false;
				foreach (ItemData candidate in new List<ItemData>(inventory2.GetAllItems()))
				{
					PlannedSlot plannedSlot = plan.FirstOrDefault((PlannedSlot cp) => cp.Item == candidate && (Object)(object)cp.TargetContainer != (Object)(object)p.TargetContainer);
					if (plannedSlot == null)
					{
						continue;
					}
					for (int num2 = containers.Count - 1; num2 >= 0; num2--)
					{
						Inventory inventory3 = containers[num2].GetInventory();
						if (inventory3 != inventory2 && inventory3.CanAddItem(candidate, -1) && inventory3.AddItem(candidate))
						{
							inventory2.RemoveItem(candidate);
							InvokeChanged(inventory2);
							InvokeChanged(inventory3);
							plannedSlot.CurrentContainer = containers[num2];
							flag = true;
							num++;
							LogLine($"  [{i}] evict {DisplayName(candidate)} x{candidate.m_stack} → Container[{num2}]");
							break;
						}
					}
					if (!flag && inventory.CanAddItem(candidate, -1))
					{
						inventory.AddItem(candidate);
						inventory2.RemoveItem(candidate);
						InvokeChanged(inventory2);
						InvokeChanged(inventory);
						plannedSlot.CurrentContainer = null;
						flag = true;
						num++;
						LogLine($"  [{i}] evict {DisplayName(candidate)} x{candidate.m_stack} → player");
					}
					if (flag)
					{
						break;
					}
				}
				if (!flag)
				{
					LogLine($"  [{i}] STUCK: {DisplayName(p.Item)} — target full, can't evict");
					continue;
				}
			}
			int num3 = inventory2.NrOfItems();
			int num4 = val.NrOfItems();
			bool flag2 = val.GetAllItems().Contains(p.Item);
			if (inventory2.AddItem(p.Item))
			{
				bool flag3 = val.GetAllItems().Contains(p.Item);
				val.RemoveItem(p.Item);
				InvokeChanged(inventory2);
				InvokeChanged(val);
				int num5 = inventory2.NrOfItems();
				int num6 = val.NrOfItems();
				p.CurrentContainer = p.TargetContainer;
				p.Done = true;
				num++;
				LogLine($"  [{i}] {DisplayName(p.Item)} x{p.Item.m_stack} → Container[{p.TargetContainerIdx}] (src:{num4}→{num6} had:{flag2} stillHas:{flag3} tgt:{num3}→{num5})");
			}
			else
			{
				LogLine($"  [{i}] FAILED: {DisplayName(p.Item)} — AddItem returned false");
			}
		}
		LogLine("\n--- Set grid positions ---");
		foreach (Container container in containers)
		{
			Inventory inventory4 = container.GetInventory();
			List<ItemData> allItems = inventory4.GetAllItems();
			if (allItems.Count == 0)
			{
				continue;
			}
			List<ItemData> list = new List<ItemData>(allItems);
			list.Sort((ItemData a, ItemData b) => CompareItems(a, b));
			int width = inventory4.GetWidth();
			for (int j = 0; j < list.Count; j++)
			{
				list[j].m_gridPos = new Vector2i(j % width, j / width);
			}
			allItems.Clear();
			allItems.AddRange(list);
			InvokeChanged(inventory4);
			int num7 = containers.IndexOf(container);
			LogLine($"  Container[{num7}]: {list.Count} items repositioned");
			foreach (ItemData item in list)
			{
				LogLine($"    ({item.m_gridPos.x},{item.m_gridPos.y}) {DisplayName(item)} x{item.m_stack}");
			}
		}
		foreach (PlannedSlot item2 in plan.Where((PlannedSlot pp) => (Object)(object)pp.CurrentContainer == (Object)null).ToList())
		{
			Inventory inventory5 = item2.TargetContainer.GetInventory();
			if (inventory5.CanAddItem(item2.Item, -1) && inventory5.AddItem(item2.Item))
			{
				inventory.RemoveItem(item2.Item);
				InvokeChanged(inventory5);
				InvokeChanged(inventory);
				item2.CurrentContainer = item2.TargetContainer;
				item2.Done = true;
				num++;
				LogLine($"  Player → Container[{item2.TargetContainerIdx}]: {DisplayName(item2.Item)} x{item2.Item.m_stack}");
			}
			else
			{
				LogLine("  WARNING: " + DisplayName(item2.Item) + " stuck in player inventory");
			}
		}
		int num8 = plan.Count((PlannedSlot pp) => !pp.Done);
		if (num8 > 0)
		{
			LogLine($"  WARNING: {num8} items not in target container");
		}
		return num;
	}

	private static int ConsolidateWithinContainer(Container container)
	{
		Inventory inventory = container.GetInventory();
		List<ItemData> allItems = inventory.GetAllItems();
		Dictionary<string, List<ItemData>> dictionary = new Dictionary<string, List<ItemData>>();
		foreach (ItemData item in allItems)
		{
			string key = ItemKey(item);
			if (!dictionary.ContainsKey(key))
			{
				dictionary[key] = new List<ItemData>();
			}
			dictionary[key].Add(item);
		}
		int num = 0;
		bool flag = false;
		foreach (KeyValuePair<string, List<ItemData>> item2 in dictionary)
		{
			List<ItemData> value = item2.Value;
			if (value.Count < 2)
			{
				continue;
			}
			int maxStackSize = value[0].m_shared.m_maxStackSize;
			if (maxStackSize <= 1)
			{
				continue;
			}
			for (int i = 0; i < value.Count; i++)
			{
				if (value[i].m_stack >= maxStackSize)
				{
					continue;
				}
				for (int num2 = value.Count - 1; num2 > i; num2--)
				{
					if (value[num2].m_stack > 0)
					{
						int num3 = Mathf.Min(maxStackSize - value[i].m_stack, value[num2].m_stack);
						if (num3 > 0)
						{
							ItemData obj = value[i];
							obj.m_stack += num3;
							ItemData obj2 = value[num2];
							obj2.m_stack -= num3;
							flag = true;
							if (value[num2].m_stack <= 0)
							{
								inventory.RemoveItem(value[num2]);
								num++;
							}
							if (value[i].m_stack >= maxStackSize)
							{
								break;
							}
						}
					}
				}
			}
		}
		if (flag)
		{
			InvokeChanged(inventory);
		}
		return num;
	}

	private static int ConsolidateAcrossContainers(List<Container> containers)
	{
		Dictionary<string, List<(Container, ItemData)>> dictionary = new Dictionary<string, List<(Container, ItemData)>>();
		foreach (Container container in containers)
		{
			foreach (ItemData allItem in container.GetInventory().GetAllItems())
			{
				string key = ItemKey(allItem);
				if (!dictionary.ContainsKey(key))
				{
					dictionary[key] = new List<(Container, ItemData)>();
				}
				dictionary[key].Add((container, allItem));
			}
		}
		int num = 0;
		foreach (KeyValuePair<string, List<(Container, ItemData)>> item3 in dictionary)
		{
			List<(Container, ItemData)> value = item3.Value;
			if (value.Count < 2)
			{
				continue;
			}
			int maxStackSize = value[0].Item2.m_shared.m_maxStackSize;
			if (maxStackSize <= 1)
			{
				continue;
			}
			value.Sort(((Container c, ItemData item) a, (Container c, ItemData item) b) => b.item.m_stack.CompareTo(a.item.m_stack));
			for (int i = 0; i < value.Count; i++)
			{
				(Container, ItemData) tuple = value[i];
				if (tuple.Item2.m_stack >= maxStackSize)
				{
					continue;
				}
				for (int num2 = value.Count - 1; num2 > i; num2--)
				{
					(Container, ItemData) tuple2 = value[num2];
					if (tuple2.Item2.m_stack > 0 && !((Object)(object)tuple2.Item1 == (Object)(object)tuple.Item1))
					{
						int num3 = Mathf.Min(maxStackSize - tuple.Item2.m_stack, tuple2.Item2.m_stack);
						if (num3 > 0)
						{
							ItemData item = tuple.Item2;
							item.m_stack += num3;
							ItemData item2 = tuple2.Item2;
							item2.m_stack -= num3;
							if (tuple2.Item2.m_stack <= 0)
							{
								tuple2.Item1.GetInventory().RemoveItem(tuple2.Item2);
								num++;
							}
							InvokeChanged(tuple.Item1.GetInventory());
							InvokeChanged(tuple2.Item1.GetInventory());
							LogLine($"  Merged {num3}x {DisplayName(tuple.Item2)}");
							if (tuple.Item2.m_stack >= maxStackSize)
							{
								break;
							}
						}
					}
				}
			}
		}
		return num;
	}

	private static void SortContainersByLayout(List<Container> containers)
	{
		//IL_0010: 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)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: 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_003c: 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_005b: 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_0069: 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_006b: 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_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: 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_0099: 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_00b8: 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_00dd: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = ((Component)Player.m_localPlayer).transform.position;
		Vector3 val = Vector3.zero;
		foreach (Container container in containers)
		{
			val += ((Component)container).transform.position;
		}
		val /= (float)containers.Count;
		Vector3 val2 = val - position;
		val2.y = 0f;
		((Vector3)(ref val2)).Normalize();
		Vector3 val3 = Vector3.Cross(Vector3.up, val2);
		Vector3 right = ((Vector3)(ref val3)).normalized;
		LogLine("\n--- SPATIAL SORT ---");
		LogLine($"  Player: ({position.x:F1},{position.y:F1},{position.z:F1})");
		LogLine($"  Chest center: ({val.x:F1},{val.y:F1},{val.z:F1})");
		LogLine($"  Right vector: ({right.x:F2},{right.y:F2},{right.z:F2})");
		containers.Sort(delegate(Container a, Container b)
		{
			//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_004a: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			Inventory inventory = a.GetInventory();
			Inventory inventory2 = b.GetInventory();
			int num = inventory.GetWidth() * inventory.GetHeight();
			int num2 = inventory2.GetWidth() * inventory2.GetHeight();
			if (num != num2)
			{
				return num2.CompareTo(num);
			}
			Vector3 position2 = ((Component)a).transform.position;
			Vector3 position3 = ((Component)b).transform.position;
			float num3 = Mathf.Round(position2.y * 2f) / 2f;
			float num4 = Mathf.Round(position3.y * 2f) / 2f;
			if (num3 != num4)
			{
				return num4.CompareTo(num3);
			}
			float num5 = Vector3.Dot(position2, right);
			float value = Vector3.Dot(position3, right);
			return num5.CompareTo(value);
		});
	}

	private static List<Container> GetNearbyContainers(float range)
	{
		//IL_000a: 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)
		//IL_0039: 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)
		Vector3 position = ((Component)Player.m_localPlayer).transform.position;
		Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0);
		List<Container> list = new List<Container>();
		Container[] array2 = array;
		foreach (Container val in array2)
		{
			if (!((Object)(object)val == (Object)null) && val.GetInventory() != null && !(Vector3.Distance(position, ((Component)val).transform.position) > range) && !val.IsInUse())
			{
				list.Add(val);
			}
		}
		return list;
	}
}
public static class InputBlocker
{
	internal static SearchUI SearchUI;

	public static bool IsBlocked()
	{
		if ((Object)(object)SearchUI != (Object)null)
		{
			return SearchUI.IsVisible;
		}
		return false;
	}
}
[HarmonyPatch(typeof(Player), "TakeInput")]
public static class PlayerTakeInputPatch
{
	private static void Postfix(ref bool __result)
	{
		if (InputBlocker.IsBlocked())
		{
			__result = false;
		}
	}
}
[HarmonyPatch(typeof(TextInput), "IsVisible")]
public static class TextInputVisiblePatch
{
	private static void Postfix(ref bool __result)
	{
		if (InputBlocker.IsBlocked())
		{
			__result = true;
		}
	}
}
[HarmonyPatch(typeof(ZInput), "GetMouseDelta")]
public static class MouseDeltaPatch
{
	private static void Postfix(ref Vector2 __result)
	{
		//IL_0008: 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)
		if (InputBlocker.IsBlocked())
		{
			__result = Vector2.zero;
		}
	}
}
[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
public static class ZInputScrollPatch
{
	private static void Postfix(ref float __result)
	{
		if (InputBlocker.IsBlocked())
		{
			__result = 0f;
		}
	}
}
[BepInPlugin("com.channel2newsteam.chestsearch", "ChestSearch", "1.0.6")]
public class Plugin : BaseUnityPlugin
{
	public const string PluginGUID = "com.channel2newsteam.chestsearch";

	public const string PluginName = "ChestSearch";

	public const string PluginVersion = "1.0.6";

	public static Plugin Instance;

	public static ConfigEntry<KeyboardShortcut> SearchHotkey;

	public static ConfigEntry<float> TakeRange;

	public static ConfigEntry<int> BuildPullVKey;

	public static ConfigEntry<float> TidyRange;

	public static ConfigEntry<float> WindowX;

	public static ConfigEntry<float> WindowY;

	private SearchUI searchUI;

	private Harmony harmony;

	private const int VK_ESCAPE = 27;

	private const int VK_F3 = 114;

	private bool wasHotkeyDown;

	private bool wasEscapeDown;

	public ManualLogSource Logger => ((BaseUnityPlugin)this).Logger;

	[DllImport("user32.dll")]
	private static extern short GetAsyncKeyState(int vKey);

	private static bool IsOSKeyDown(int vKey)
	{
		return (GetAsyncKeyState(vKey) & 0x8000) != 0;
	}

	private void Awake()
	{
		//IL_0020: 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_00f5: Expected O, but got Unknown
		Instance = this;
		SearchHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "SearchHotkey", new KeyboardShortcut((KeyCode)284, Array.Empty<KeyCode>()), "Hotkey to open the chest search window");
		TakeRange = ((BaseUnityPlugin)this).Config.Bind<float>("General", "TakeRange", 30f, "Maximum distance to remotely take items from containers (meters)");
		BuildPullVKey = ((BaseUnityPlugin)this).Config.Bind<int>("General", "BuildPullVKey", 90, "Windows virtual key code for auto-pull while building. Default: 0x5A (Z). Set to 0 to disable. Common: 0xA0=LShift, 0xA2=LCtrl, 0xA4=LAlt. See https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes");
		TidyRange = ((BaseUnityPlugin)this).Config.Bind<float>("General", "TidyRange", 15f, "Maximum distance for the Tidy feature to organize containers (meters)");
		WindowX = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowX", 20f, "Window X position");
		WindowY = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowY", 20f, "Window Y position");
		harmony = new Harmony("com.channel2newsteam.chestsearch");
		harmony.PatchAll(Assembly.GetExecutingAssembly());
		Logger.LogInfo((object)"ChestSearch v1.0.6 loaded!");
	}

	private void Update()
	{
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Expected O, but got Unknown
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			return;
		}
		bool flag = IsOSKeyDown(114);
		bool flag2 = IsOSKeyDown(27);
		bool num = flag && !wasHotkeyDown;
		bool flag3 = flag2 && !wasEscapeDown;
		wasHotkeyDown = flag;
		wasEscapeDown = flag2;
		bool flag4 = (Object)(object)searchUI != (Object)null && searchUI.IsVisible;
		if (num)
		{
			if ((Object)(object)searchUI == (Object)null)
			{
				GameObject val = new GameObject("ChestSearchUI");
				Object.DontDestroyOnLoad((Object)(object)val);
				searchUI = val.AddComponent<SearchUI>();
			}
			else
			{
				searchUI.Toggle();
			}
		}
		else if (flag3 && flag4)
		{
			searchUI.Toggle();
		}
	}

	private void OnDestroy()
	{
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}
}
public class SearchUI : MonoBehaviour
{
	private bool isVisible;

	private string searchText = "";

	private string lastSearchText = "";

	private List<SearchResult> results = new List<SearchResult>();

	private Vector2 scrollPosition;

	private float searchCooldown;

	private int selectedIndex = -1;

	private string statusMessage = "";

	private float statusTimer;

	private bool needsFocus;

	private float toggleCooldown;

	private Rect windowRect;

	private const int WindowID = 94317;

	private GUIStyle windowStyle;

	private GUIStyle headerStyle;

	private GUIStyle searchBoxStyle;

	private GUIStyle resultHeaderStyle;

	private GUIStyle resultHeaderInRangeStyle;

	private GUIStyle selectedHeaderStyle;

	private GUIStyle selectedHeaderInRangeStyle;

	private GUIStyle itemStyle;

	private GUIStyle pingButtonStyle;

	private GUIStyle takeButtonStyle;

	private GUIStyle closeButtonStyle;

	private GUIStyle hintStyle;

	private bool stylesInitialized;

	public bool IsVisible => isVisible;

	private void Start()
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		InputBlocker.SearchUI = this;
		windowRect = new Rect(Plugin.WindowX.Value, Plugin.WindowY.Value, 420f, 500f);
		isVisible = true;
		Open();
	}

	public void Toggle()
	{
		if (!(toggleCooldown > 0f))
		{
			isVisible = !isVisible;
			toggleCooldown = 0.2f;
			if (isVisible)
			{
				Open();
			}
			else
			{
				Close();
			}
		}
	}

	private void Open()
	{
		searchText = "";
		lastSearchText = "";
		results.Clear();
		selectedIndex = -1;
		GUIUtility.keyboardControl = 0;
		needsFocus = true;
		SetCursor(show: true);
	}

	private void Close()
	{
		isVisible = false;
		toggleCooldown = 0.2f;
		SetCursor(show: false);
	}

	private static void SetCursor(bool show)
	{
		Cursor.lockState = (CursorLockMode)((!show) ? 1 : 0);
		Cursor.visible = show;
	}

	private void Update()
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		if (toggleCooldown > 0f)
		{
			toggleCooldown -= Time.deltaTime;
		}
		if (!isVisible)
		{
			return;
		}
		if ((int)Cursor.lockState != 0)
		{
			SetCursor(show: true);
		}
		if (statusTimer > 0f)
		{
			statusTimer -= Time.deltaTime;
		}
		if (searchText != lastSearchText)
		{
			searchCooldown = 0.25f;
			lastSearchText = searchText;
		}
		if (searchCooldown > 0f)
		{
			searchCooldown -= Time.deltaTime;
			if (searchCooldown <= 0f)
			{
				PerformSearch();
			}
		}
	}

	private void PerformSearch()
	{
		if (searchText.Length >= 2)
		{
			results = ContainerSearcher.Search(searchText);
			selectedIndex = ((results.Count <= 0) ? (-1) : 0);
		}
		else
		{
			results.Clear();
			selectedIndex = -1;
		}
	}

	private void InitStyles()
	{
		//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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		//IL_0031: Expected O, but got Unknown
		//IL_003c: 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_0049: 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_005c: Expected O, but got Unknown
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: 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_00a3: 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_00b2: Expected O, but got Unknown
		//IL_00b7: Expected O, but got Unknown
		//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_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Expected O, but got Unknown
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Expected O, but got Unknown
		//IL_013d: 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)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Expected O, but got Unknown
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Expected O, but got Unknown
		//IL_01cd: 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_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Expected O, but got Unknown
		//IL_0204: Expected O, but got Unknown
		//IL_021e: 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_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_0240: Unknown result type (might be due to invalid IL or missing references)
		//IL_024b: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Expected O, but got Unknown
		//IL_0266: Unknown result type (might be due to invalid IL or missing references)
		//IL_026b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		//IL_027e: Unknown result type (might be due to invalid IL or missing references)
		//IL_028e: Expected O, but got Unknown
		//IL_0299: Unknown result type (might be due to invalid IL or missing references)
		//IL_029e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c8: Expected O, but got Unknown
		//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f3: Expected O, but got Unknown
		//IL_030d: Unknown result type (might be due to invalid IL or missing references)
		if (!stylesInitialized)
		{
			windowStyle = new GUIStyle(GUI.skin.window)
			{
				padding = new RectOffset(10, 10, 20, 10)
			};
			headerStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = 16,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4
			};
			headerStyle.normal.textColor = new Color(1f, 0.85f, 0.4f);
			searchBoxStyle = new GUIStyle(GUI.skin.textField)
			{
				fontSize = 16,
				fixedHeight = 30f,
				padding = new RectOffset(8, 8, 4, 4)
			};
			resultHeaderStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = 13,
				fontStyle = (FontStyle)1
			};
			resultHeaderStyle.normal.textColor = new Color(0.6f, 0.9f, 1f);
			resultHeaderInRangeStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = 13,
				fontStyle = (FontStyle)1
			};
			resultHeaderInRangeStyle.normal.textColor = new Color(0.4f, 1f, 0.4f);
			selectedHeaderStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = 13,
				fontStyle = (FontStyle)1
			};
			selectedHeaderStyle.normal.textColor = new Color(1f, 0.95f, 0.5f);
			selectedHeaderInRangeStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = 13,
				fontStyle = (FontStyle)1
			};
			selectedHeaderInRangeStyle.normal.textColor = new Color(0.6f, 1f, 0.3f);
			itemStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = 12,
				padding = new RectOffset(15, 0, 0, 0)
			};
			itemStyle.normal.textColor = new Color(0.9f, 0.9f, 0.9f);
			pingButtonStyle = new GUIStyle(GUI.skin.button)
			{
				fontSize = 11,
				fixedWidth = 50f,
				fixedHeight = 20f
			};
			takeButtonStyle = new GUIStyle(GUI.skin.button)
			{
				fontSize = 11,
				fixedWidth = 50f,
				fixedHeight = 18f
			};
			closeButtonStyle = new GUIStyle(GUI.skin.button)
			{
				fontSize = 14,
				fontStyle = (FontStyle)1,
				fixedWidth = 24f,
				fixedHeight = 24f
			};
			hintStyle = new GUIStyle(GUI.skin.label)
			{
				fontSize = 11,
				fontStyle = (FontStyle)2,
				alignment = (TextAnchor)4
			};
			hintStyle.normal.textColor = new Color(0.85f, 0.85f, 0.7f);
			stylesInitialized = true;
		}
	}

	private void OnGUI()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Invalid comparison between Unknown and I4
		//IL_0236: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: Expected O, but got Unknown
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: 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_004c: Invalid comparison between Unknown and I4
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Invalid comparison between Unknown and I4
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Invalid comparison between Unknown and I4
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Invalid comparison between Unknown and I4
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Invalid comparison between Unknown and I4
		if (!isVisible || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			return;
		}
		InitStyles();
		if ((int)Event.current.type == 4 && results.Count > 0)
		{
			if ((int)Event.current.keyCode == 274)
			{
				selectedIndex = Mathf.Min(selectedIndex + 1, results.Count - 1);
				ScrollToSelected();
				Event.current.Use();
			}
			else if ((int)Event.current.keyCode == 273)
			{
				selectedIndex = Mathf.Max(selectedIndex - 1, 0);
				ScrollToSelected();
				Event.current.Use();
			}
			else if ((int)Event.current.keyCode == 13 || (int)Event.current.keyCode == 271)
			{
				if (selectedIndex >= 0 && selectedIndex < results.Count)
				{
					ContainerSearcher.PingContainer(results[selectedIndex].Container);
					Event.current.Use();
				}
			}
			else if ((int)Event.current.keyCode == 9 && selectedIndex >= 0 && selectedIndex < results.Count)
			{
				SearchResult searchResult = results[selectedIndex];
				float value = Plugin.TakeRange.Value;
				if (searchResult.Distance <= value)
				{
					int num = 0;
					foreach (ItemMatch item in searchResult.Items)
					{
						num += ContainerSearcher.TakeItems(searchResult.Container, item.ItemKey, value);
					}
					if (num > 0)
					{
						SetStatus($"Took {num} items from {searchResult.ContainerName}");
						PerformSearch();
					}
					else
					{
						SetStatus("Inventory full");
					}
				}
				else
				{
					SetStatus($"Too far ({searchResult.Distance:F0}m, need {value:F0}m)");
				}
				Event.current.Use();
			}
		}
		GUI.depth = 0;
		windowRect = GUI.Window(94317, windowRect, new WindowFunction(DrawWindow), "", windowStyle);
		((Rect)(ref windowRect)).x = Mathf.Clamp(((Rect)(ref windowRect)).x, 0f, (float)Screen.width - ((Rect)(ref windowRect)).width);
		((Rect)(ref windowRect)).y = Mathf.Clamp(((Rect)(ref windowRect)).y, 0f, (float)Screen.height - ((Rect)(ref windowRect)).height);
		if (!Input.GetMouseButton(0) && (((Rect)(ref windowRect)).x != Plugin.WindowX.Value || ((Rect)(ref windowRect)).y != Plugin.WindowY.Value))
		{
			Plugin.WindowX.Value = ((Rect)(ref windowRect)).x;
			Plugin.WindowY.Value = ((Rect)(ref windowRect)).y;
		}
	}

	private void DrawWindow(int id)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0232: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_0255: Unknown result type (might be due to invalid IL or missing references)
		GUI.Label(new Rect(10f, 4f, ((Rect)(ref windowRect)).width - 50f, 30f), "Chest Search", headerStyle);
		if (GUI.Button(new Rect(((Rect)(ref windowRect)).width - 34f, 4f, 24f, 24f), "X", closeButtonStyle))
		{
			Close();
			return;
		}
		GUILayout.Space(35f);
		GUI.SetNextControlName("ChestSearchField");
		searchText = GUILayout.TextField(searchText, searchBoxStyle, Array.Empty<GUILayoutOption>());
		if (needsFocus)
		{
			GUI.FocusControl("ChestSearchField");
			needsFocus = false;
		}
		GUILayout.Space(5f);
		if (searchText.Length < 2)
		{
			GUILayout.Label("Type at least 2 characters to search...", hintStyle, Array.Empty<GUILayoutOption>());
		}
		else if (results.Count == 0)
		{
			GUILayout.Label("No containers found with \"" + searchText + "\"", hintStyle, Array.Empty<GUILayoutOption>());
		}
		else
		{
			int num = 0;
			float value = Plugin.TakeRange.Value;
			int num2 = 0;
			foreach (SearchResult result in results)
			{
				foreach (ItemMatch item in result.Items)
				{
					num += item.Stack;
				}
				if (result.Distance <= value)
				{
					num2++;
				}
			}
			GUILayout.Label($"{num} items across {results.Count} containers ({num2} in take range)", hintStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(3f);
			scrollPosition = GUILayout.BeginScrollView(scrollPosition, Array.Empty<GUILayoutOption>());
			for (int i = 0; i < results.Count; i++)
			{
				SearchResult searchResult = results[i];
				bool num3 = i == selectedIndex;
				if (num3)
				{
					Rect rect = GUILayoutUtility.GetRect(0f, 0f);
					((Rect)(ref rect)).height = 20 + searchResult.Items.Count * 18 + 6;
					GUI.Box(rect, GUIContent.none);
				}
				float value2 = Plugin.TakeRange.Value;
				bool flag = searchResult.Distance <= value2;
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUIStyle val = ((!num3) ? (flag ? resultHeaderInRangeStyle : resultHeaderStyle) : (flag ? selectedHeaderInRangeStyle : selectedHeaderStyle));
				GUILayout.Label($"{searchResult.ContainerName}  ({searchResult.Distance:F0}m)", val, Array.Empty<GUILayoutOption>());
				GUILayout.FlexibleSpace();
				if (GUILayout.Button("Ping", pingButtonStyle, Array.Empty<GUILayoutOption>()))
				{
					ContainerSearcher.PingContainer(searchResult.Container);
				}
				GUILayout.EndHorizontal();
				foreach (ItemMatch item2 in searchResult.Items)
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Label($"  {item2.Name}{item2.QualityText}  x{item2.Stack}", itemStyle, Array.Empty<GUILayoutOption>());
					GUILayout.FlexibleSpace();
					if (flag && GUILayout.Button("Take", takeButtonStyle, Array.Empty<GUILayoutOption>()))
					{
						int num4 = ContainerSearcher.TakeItems(searchResult.Container, item2.ItemKey, value2);
						if (num4 > 0)
						{
							SetStatus($"Took {num4}x {item2.Name}");
							PerformSearch();
						}
						else
						{
							SetStatus("Inventory full");
						}
					}
					GUILayout.EndHorizontal();
				}
				GUILayout.Space(6f);
			}
			GUILayout.EndScrollView();
		}
		GUILayout.Space(5f);
		if (GUILayout.Button($"Tidy Nearby Containers ({Plugin.TidyRange.Value:F0}m)", Array.Empty<GUILayoutOption>()))
		{
			string status = ContainerTidy.Tidy(Plugin.TidyRange.Value);
			SetStatus(status);
			if (searchText.Length >= 2)
			{
				PerformSearch();
			}
		}
		if (statusTimer > 0f)
		{
			GUILayout.Space(3f);
			GUILayout.Label(statusMessage, hintStyle, Array.Empty<GUILayoutOption>());
		}
		GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref windowRect)).width - 40f, 30f));
	}

	private void ScrollToSelected()
	{
		if (selectedIndex < 0 || selectedIndex >= results.Count)
		{
			return;
		}
		float num = 0f;
		float num2 = 0f;
		for (int i = 0; i < results.Count; i++)
		{
			float num3 = 24 + results[i].Items.Count * 22 + 10;
			if (i < selectedIndex)
			{
				num2 += num3;
			}
			if (i == selectedIndex)
			{
				num = num3;
			}
		}
		float num4 = ((Rect)(ref windowRect)).height - 180f;
		float num5 = 30f;
		if (num2 < scrollPosition.y)
		{
			scrollPosition.y = num2;
		}
		else if (num2 + num + num5 > scrollPosition.y + num4)
		{
			scrollPosition.y = num2 + num + num5 - num4;
		}
	}

	private void SetStatus(string msg)
	{
		statusMessage = msg;
		statusTimer = 3f;
	}
}