Decompiled source of Carturs Map Pins v1.5.0

plugins/CarturMapPins.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
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("CarturMapPins")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+9be7b5e1c1b78d5a4b0251aae77be317caa7259a")]
[assembly: AssemblyProduct("CarturMapPins")]
[assembly: AssemblyTitle("CarturMapPins")]
[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 CarturMapPins
{
	internal class CellHover : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		private const float HoverScale = 1.12f;

		private const float Speed = 12f;

		private Image _border;

		private float _target = 1f;

		private bool _animating;

		public void Bind(Image border)
		{
			_border = border;
		}

		public void OnPointerEnter(PointerEventData eventData)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			_target = 1.12f;
			_animating = true;
			if ((Object)(object)_border != (Object)null && ((Graphic)_border).color != IconGrid.Selected)
			{
				((Graphic)_border).color = IconGrid.Hovered;
			}
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			_target = 1f;
			_animating = true;
			if ((Object)(object)_border != (Object)null && ((Graphic)_border).color != IconGrid.Selected)
			{
				((Graphic)_border).color = IconGrid.Resting;
			}
		}

		private void Update()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (_animating)
			{
				float num = Mathf.Lerp(((Component)this).transform.localScale.x, _target, Time.unscaledDeltaTime * 12f);
				if (Mathf.Abs(num - _target) < 0.005f)
				{
					num = _target;
					_animating = false;
				}
				((Component)this).transform.localScale = new Vector3(num, num, 1f);
			}
		}
	}
	internal static class ChestRegistry
	{
		private static readonly List<Container> Live = new List<Container>();

		public static void Add(Container container)
		{
			if (!((Object)(object)container == (Object)null) && !Live.Contains(container))
			{
				Live.Add(container);
			}
		}

		public static void Clear()
		{
			Live.Clear();
		}

		public static IEnumerable<Container> Alive()
		{
			for (int i = Live.Count - 1; i >= 0; i--)
			{
				if ((Object)(object)Live[i] == (Object)null)
				{
					Live.RemoveAt(i);
				}
				else
				{
					yield return Live[i];
				}
			}
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public bool? Browsable;

		public bool? IsAdvanced;

		public int? Order;

		public Action<ConfigEntryBase> CustomDrawer;
	}
	internal static class Crowding
	{
		private const float FallbackIconPixels = 32f;

		private const float Floor = 0.5f;

		private static float _iconPixels = 32f;

		private static float _cellMetres = 1f;

		private static float _zoom = 1f;

		private static readonly Dictionary<long, int> Counts = new Dictionary<long, int>();

		private static readonly Dictionary<string, int> NameCounts = new Dictionary<string, int>();

		private static readonly Dictionary<long, PinData> Winners = new Dictionary<long, PinData>();

		private static readonly Dictionary<long, PinData> Survivors = new Dictionary<long, PinData>();

		private static readonly HashSet<PinData> NotDrawn = new HashSet<PinData>();

		private static long CellFor(PinData pin)
		{
			int num = Mathf.RoundToInt(pin.m_pos.x / _cellMetres);
			int num2 = Mathf.RoundToInt(pin.m_pos.z / _cellMetres);
			return ((long)num << 32) ^ (uint)num2;
		}

		private static long MergeKey(long cell, string name)
		{
			return cell * 31 + name.GetHashCode();
		}

		private static bool Precedes(PinData a, PinData b)
		{
			if (!Mathf.Approximately(a.m_pos.x, b.m_pos.x))
			{
				return a.m_pos.x < b.m_pos.x;
			}
			return a.m_pos.z < b.m_pos.z;
		}

		private static float ScaleForCount(int count)
		{
			if (count <= 1)
			{
				return 1f;
			}
			if (count == 2)
			{
				return 0.9f;
			}
			if (count <= 4)
			{
				return 0.8f;
			}
			if (count <= 6)
			{
				return 0.65f;
			}
			return 0.5f;
		}

		public static float ZoomOutPercent()
		{
			return ZoomOutPercent(Minimap.instance);
		}

		public static float ZoomOutPercent(Minimap map)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			if ((Object)(object)map == (Object)null)
			{
				return 0f;
			}
			float num = (((int)map.m_mode == 2) ? map.LargeZoom : map.SmallZoom);
			return Mathf.InverseLerp(map.m_minZoom, map.m_maxZoom, num) * 100f;
		}

		private static float ZoomScale(Minimap map)
		{
			float num = Mathf.Clamp(Plugin.ZoomedOutPinScale.Value, 0.2f, 1f);
			if ((Object)(object)map == (Object)null || num >= 1f)
			{
				return 1f;
			}
			float num2 = Mathf.InverseLerp(Mathf.Clamp(Plugin.ShrinkPinsFromZoom.Value, 0f, 100f), 100f, ZoomOutPercent(map));
			return Mathf.Lerp(1f, num, num2);
		}

		private static float CellMetres(Minimap map)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//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)
			RawImage val = (((int)map.m_mode == 2) ? map.m_mapImageLarge : map.m_mapImageSmall);
			float num = (((int)map.m_mode == 2) ? map.LargeZoom : map.SmallZoom);
			float num2;
			if (!((Object)(object)val != (Object)null))
			{
				num2 = 0f;
			}
			else
			{
				Rect rect = ((Graphic)val).rectTransform.rect;
				num2 = ((Rect)(ref rect)).height;
			}
			float num3 = num2;
			float num4 = (float)map.m_textureSize * map.m_pixelSize;
			if (num3 < 1f || num4 <= 0f || num <= 0f)
			{
				return _cellMetres;
			}
			return _iconPixels * (num * num4 / num3);
		}

		private static float HideRangeSqr()
		{
			float value = Plugin.HidePinsBeyond.Value;
			if (!(value > 0f))
			{
				return 0f;
			}
			return value * value;
		}

		public static void Measure(List<PinData> pins)
		{
			//IL_009e: 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_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: 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)
			Counts.Clear();
			NameCounts.Clear();
			Winners.Clear();
			Survivors.Clear();
			NotDrawn.Clear();
			Minimap instance = Minimap.instance;
			_zoom = ZoomScale(instance);
			if ((Object)(object)instance == (Object)null || pins == null)
			{
				return;
			}
			float num = float.MaxValue;
			foreach (PinData pin in pins)
			{
				if (!((Object)(object)pin?.m_iconElement == (Object)null) && ((Component)pin.m_iconElement).gameObject.activeInHierarchy)
				{
					Rect rect = ((Graphic)pin.m_iconElement).rectTransform.rect;
					float width = ((Rect)(ref rect)).width;
					if (width > 1f && width < num)
					{
						num = width;
					}
				}
			}
			if (num < float.MaxValue)
			{
				_iconPixels = num;
			}
			_cellMetres = CellMetres(instance);
			if (_cellMetres <= 0f)
			{
				return;
			}
			float num2 = HideRangeSqr();
			Player localPlayer = Player.m_localPlayer;
			bool flag = num2 > 0f && (Object)(object)localPlayer != (Object)null;
			Vector3 val = (((Object)(object)localPlayer != (Object)null) ? ((Component)localPlayer).transform.position : Vector3.zero);
			bool value = Plugin.ShrinkCrowdedPins.Value;
			bool value2 = Plugin.MergeRepeatedPins.Value;
			foreach (PinData pin2 in pins)
			{
				if (pin2 == null)
				{
					continue;
				}
				if (IsVanillaSpawnDuplicate(pin2))
				{
					NotDrawn.Add(pin2);
					continue;
				}
				if (flag)
				{
					float num3 = pin2.m_pos.x - val.x;
					float num4 = pin2.m_pos.z - val.z;
					if (num3 * num3 + num4 * num4 > num2)
					{
						NotDrawn.Add(pin2);
						continue;
					}
				}
				if (value2)
				{
					long key = MergeKey(CellFor(pin2), pin2.m_name ?? string.Empty);
					if (!Survivors.TryGetValue(key, out var value3) || Precedes(pin2, value3))
					{
						Survivors[key] = pin2;
					}
				}
			}
			if (!value && !value2)
			{
				return;
			}
			foreach (PinData pin3 in pins)
			{
				if (pin3 != null && !NotDrawn.Contains(pin3))
				{
					string text = pin3.m_name ?? string.Empty;
					long num5 = CellFor(pin3);
					if (value2 && Survivors.TryGetValue(MergeKey(num5, text), out var value4) && value4 != pin3)
					{
						NotDrawn.Add(pin3);
					}
					else if (value)
					{
						Counts.TryGetValue(num5, out var value5);
						Counts[num5] = value5 + 1;
						NameCounts.TryGetValue(text, out var value6);
						NameCounts[text] = value6 + 1;
					}
				}
			}
			if (!value)
			{
				return;
			}
			foreach (PinData pin4 in pins)
			{
				if (pin4 == null || NotDrawn.Contains(pin4))
				{
					continue;
				}
				long key2 = CellFor(pin4);
				if (!Winners.TryGetValue(key2, out var value7))
				{
					Winners[key2] = pin4;
					continue;
				}
				int num6 = Rarity(pin4);
				int num7 = Rarity(value7);
				if (num6 < num7 || (num6 == num7 && Precedes(pin4, value7)))
				{
					Winners[key2] = pin4;
				}
			}
		}

		private static int Rarity(PinData pin)
		{
			NameCounts.TryGetValue(pin.m_name ?? string.Empty, out var value);
			return value;
		}

		public static bool OutOfSight(PinData pin)
		{
			return NotDrawn.Contains(pin);
		}

		public static float ScaleFor(PinData pin)
		{
			if (pin == null)
			{
				return _zoom;
			}
			long key = CellFor(pin);
			if (!Counts.TryGetValue(key, out var value) || value <= 1)
			{
				return _zoom;
			}
			if (Winners.TryGetValue(key, out var value2) && value2 == pin)
			{
				return _zoom;
			}
			return _zoom * ScaleForCount(value);
		}

		public static string Describe()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return "no map";
			}
			float num = (((int)instance.m_mode == 2) ? instance.LargeZoom : instance.SmallZoom);
			return $"mode={instance.m_mode} zoom={num:F4} ({ZoomOutPercent(instance):F0}% out) " + $"min={instance.m_minZoom:F4} max={instance.m_maxZoom:F4} " + $"shrinkFrom={Plugin.ShrinkPinsFromZoom.Value:F0}% floor={Plugin.ZoomedOutPinScale.Value:F2} " + $"=> zoomScale={_zoom:F3}, icon={_iconPixels:F0}px, cell={_cellMetres:F0}m, " + $"cells={Counts.Count}, notDrawn={NotDrawn.Count}";
		}

		private static bool IsVanillaSpawnDuplicate(PinData pin)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (pin.m_save || (int)pin.m_type != 5)
			{
				return false;
			}
			Plugin.CategorySettings categorySettings = Plugin.SettingsFor(PinCategory.Home);
			if (categorySettings == null || !categorySettings.Enabled.Value)
			{
				return false;
			}
			return PinRecord.HasCategoryNear(PinCategory.Home, pin.m_pos, categorySettings.DedupeRadius.Value);
		}
	}
	internal static class CustomIcons
	{
		public const int FirstCustomType = 100;

		private const int SheetColumns = 10;

		public static readonly int IconCount = Enum.GetValues(typeof(PinIcon)).Length - 1;

		private const int LegacyIconCount = 83;

		private static Sprite[] _legacy;

		public const int CurrentBase = 183;

		private static Sprite[] _sprites;

		private static Minimap _registeredFor;

		public static Sprite[] Sprites => _sprites;

		public static bool Ready => _sprites != null;

		public static int Count
		{
			get
			{
				Sprite[] sprites = _sprites;
				if (sprites == null)
				{
					return 0;
				}
				return sprites.Length;
			}
		}

		public static int LegacyCount
		{
			get
			{
				Sprite[] legacy = _legacy;
				if (legacy == null)
				{
					return 0;
				}
				return legacy.Length;
			}
		}

		public static int PickerCount => Count + LegacyCount;

		public static Sprite SpriteAt(int index)
		{
			if (_sprites == null || index < 0 || index >= _sprites.Length)
			{
				return null;
			}
			return _sprites[index];
		}

		public static PinType TypeForIndex(int index)
		{
			return (PinType)(183 + index);
		}

		public static PinType LegacyTypeForIndex(int index)
		{
			return (PinType)(100 + index);
		}

		public static Sprite SpriteForPicker(int index)
		{
			if (index >= Count)
			{
				if (_legacy == null || index - Count >= _legacy.Length)
				{
					return null;
				}
				return _legacy[index - Count];
			}
			return SpriteAt(index);
		}

		public static PinType TypeForPicker(int index)
		{
			//IL_0016: 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)
			if (index >= Count)
			{
				return LegacyTypeForIndex(index - Count);
			}
			return TypeForIndex(index);
		}

		public static bool IsCustom(PinType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			return (int)type >= 100;
		}

		public static int PickerIndexFor(PinType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Expected I4, but got Unknown
			int num = (int)type;
			if (num >= 183)
			{
				if (num - 183 >= Count)
				{
					return -1;
				}
				return num - 183;
			}
			if (num >= 100)
			{
				if (num - 100 >= LegacyCount)
				{
					return -1;
				}
				return Count + (num - 100);
			}
			return -1;
		}

		public static PinType Resolve(int iconIndex, PinType fallback)
		{
			//IL_0013: 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_0030: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.CustomIconsEnabled.Value || !Ready)
			{
				return fallback;
			}
			if (iconIndex >= 1000)
			{
				int num = iconIndex - 1000;
				if (num >= LegacyCount)
				{
					return fallback;
				}
				return LegacyTypeForIndex(num);
			}
			if (iconIndex < 0 || iconIndex >= Count)
			{
				return fallback;
			}
			return TypeForIndex(iconIndex);
		}

		public static void Register(Minimap map)
		{
			if ((Object)(object)map == (Object)null || (Object)(object)_registeredFor == (Object)(object)map || !Reserve(map))
			{
				return;
			}
			if (!Plugin.CustomIconsEnabled.Value)
			{
				FallbackSprites(map);
				return;
			}
			try
			{
				if (_sprites == null)
				{
					Texture2D val = LoadSheet();
					if ((Object)(object)val == (Object)null)
					{
						FallbackSprites(map);
						return;
					}
					_sprites = Slice(val, IconCount);
				}
				if (_legacy == null)
				{
					Texture2D val2 = LoadSheet("pin_icons_legacy.png");
					_legacy = (Sprite[])(((Object)(object)val2 != (Object)null) ? ((Array)Slice(val2, 83)) : ((Array)new Sprite[0]));
				}
				int num = Register(map, _sprites, TypeForIndex) + Register(map, _legacy, LegacyTypeForIndex);
				ReplaceBedSprite(map);
				_registeredFor = map;
				Plugin.Log.LogInfo((object)($"Registered {num} custom pin icons: {_sprites.Length} current on types " + $"{183}-{183 + _sprites.Length - 1}, " + $"{LegacyCount} from 1.2.2's sheet on {100}-{100 + LegacyCount - 1}."));
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Custom icons failed to register, falling back to vanilla pin types: {arg}");
				_sprites = null;
				_registeredFor = null;
			}
		}

		private static bool Reserve(Minimap map)
		{
			try
			{
				GrowVisibleIconTypes(map, 183 + IconCount + 1);
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not reserve the custom pin types: " + ex.Message));
				return false;
			}
		}

		private static void FallbackSprites(Minimap map)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0035: 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)
			Sprite val = VanillaSprite(map, (PinType)3);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			int num = 0;
			for (int i = 100; i < 183 + IconCount; i++)
			{
				PinType val2 = (PinType)i;
				if (!AlreadyRegistered(map, val2))
				{
					map.m_icons.Add(new SpriteData
					{
						m_name = val2,
						m_icon = val
					});
					num++;
				}
			}
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)$"Custom icons unavailable - {num} custom pin type(s) drawing vanilla's Icon3. The pins keep their own type and come back when icons are switched on.");
			}
		}

		private static Sprite VanillaSprite(Minimap map, PinType type)
		{
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			foreach (SpriteData icon in map.m_icons)
			{
				if (icon.m_name == type)
				{
					return icon.m_icon;
				}
			}
			return null;
		}

		private static void ReplaceBedSprite(Minimap map)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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)
			if (!Plugin.ReplaceBedMarker.Value)
			{
				return;
			}
			Plugin.CategorySettings categorySettings = Plugin.SettingsFor(PinCategory.Home);
			if (categorySettings == null)
			{
				return;
			}
			Sprite val = SpriteFor((int)categorySettings.IconIndex.Value);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			for (int i = 0; i < map.m_icons.Count; i++)
			{
				if ((int)map.m_icons[i].m_name == 5)
				{
					SpriteData value = map.m_icons[i];
					value.m_icon = val;
					map.m_icons[i] = value;
					break;
				}
			}
		}

		private static Sprite SpriteFor(int iconIndex)
		{
			if (_sprites == null || iconIndex < 0 || iconIndex >= _sprites.Length)
			{
				return null;
			}
			return _sprites[iconIndex];
		}

		private static int Register(Minimap map, Sprite[] sprites, Func<int, PinType> typeFor)
		{
			//IL_0019: 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_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_004b: Unknown result type (might be due to invalid IL or missing references)
			if (sprites == null)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < sprites.Length; i++)
			{
				if (!((Object)(object)sprites[i] == (Object)null) && !AlreadyRegistered(map, typeFor(i)))
				{
					map.m_icons.Add(new SpriteData
					{
						m_name = typeFor(i),
						m_icon = sprites[i]
					});
					num++;
				}
			}
			return num;
		}

		private static bool AlreadyRegistered(Minimap map, PinType type)
		{
			//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_001a: Unknown result type (might be due to invalid IL or missing references)
			foreach (SpriteData icon in map.m_icons)
			{
				if (icon.m_name == type)
				{
					return true;
				}
			}
			return false;
		}

		private static Texture2D LoadSheetFromResource(string resource)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("CarturMapPins." + resource);
			if (stream == null)
			{
				Plugin.Log.LogError((object)("Embedded icon sheet " + resource + " not found."));
				return null;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!LoadImageViaReflection(val, array))
			{
				return null;
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			return val;
		}

		private static Texture2D LoadSheet(string resource = "pin_icons.png")
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			bool num = resource == "pin_icons.png";
			string text = Path.Combine(Paths.ConfigPath, "carturmappins_icons.png");
			bool flag = num && File.Exists(text);
			byte[] array;
			if (flag)
			{
				array = File.ReadAllBytes(text);
				Plugin.Log.LogInfo((object)("Loading icon sheet override from " + text));
			}
			else
			{
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("CarturMapPins." + resource);
				if (stream == null)
				{
					Plugin.Log.LogError((object)("Embedded icon sheet " + resource + " not found."));
					return null;
				}
				array = new byte[stream.Length];
				stream.Read(array, 0, array.Length);
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!LoadImageViaReflection(val, array))
			{
				return null;
			}
			if (flag)
			{
				int num2 = 10;
				float num3 = (float)((Texture)val).width / (float)num2;
				int num4 = ((num3 > 0f) ? (num2 * Mathf.FloorToInt((float)((Texture)val).height / num3)) : 0);
				if (num4 < IconCount)
				{
					Plugin.Log.LogWarning((object)($"The icon sheet override at {text} holds {num4} icons and this version needs {IconCount} " + $"- it was drawn for an older sheet. Using the bundled one instead; redraw it at {10} columns " + "with enough rows, or remove the file."));
					return LoadSheetFromResource(resource);
				}
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			return val;
		}

		private static bool LoadImageViaReflection(Texture2D tex, byte[] data)
		{
			Type type = AccessTools.TypeByName("UnityEngine.ImageConversion");
			if (type == null)
			{
				Plugin.Log.LogError((object)"UnityEngine.ImageConversion not found; cannot decode the icon sheet.");
				return false;
			}
			MethodInfo methodInfo = null;
			MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public);
			foreach (MethodInfo methodInfo2 in methods)
			{
				if (!(methodInfo2.Name != "LoadImage"))
				{
					ParameterInfo[] parameters = methodInfo2.GetParameters();
					if (parameters.Length == 3 && parameters[1].ParameterType == typeof(byte[]))
					{
						methodInfo = methodInfo2;
						break;
					}
				}
			}
			if (methodInfo == null)
			{
				Plugin.Log.LogError((object)"No LoadImage(Texture2D, byte[], bool) overload found.");
				return false;
			}
			object obj = methodInfo.Invoke(null, new object[3] { tex, data, false });
			bool flag = default(bool);
			int num;
			if (obj is bool)
			{
				flag = (bool)obj;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		private static Sprite[] Slice(Texture2D sheet, int count)
		{
			//IL_004b: 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)
			float num = (float)((Texture)sheet).width / 10f;
			Sprite[] array = (Sprite[])(object)new Sprite[count];
			Rect val = default(Rect);
			for (int i = 0; i < count; i++)
			{
				int num2 = i % 10;
				int num3 = i / 10;
				float num4 = (float)num2 * num;
				float num5 = (float)num3 * num;
				float num6 = (float)((Texture)sheet).height - num5 - num;
				((Rect)(ref val))..ctor(num4, num6, num, num);
				array[i] = Sprite.Create(sheet, val, new Vector2(0.5f, 0.5f));
				((Object)array[i]).name = $"CarturPin_{i}";
			}
			return array;
		}

		private static void GrowVisibleIconTypes(Minimap map, int size)
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(Minimap), "m_visibleIconTypes");
			if (fieldInfo == null)
			{
				throw new InvalidOperationException("Minimap.m_visibleIconTypes not found - refusing to register custom icons, since AddPin would silently rewrite them to Icon3 in the save.");
			}
			bool[] array = fieldInfo.GetValue(map) as bool[];
			int num = ((array != null) ? array.Length : 0);
			if (num < size)
			{
				bool[] array2 = new bool[size];
				for (int i = 0; i < size; i++)
				{
					array2[i] = i >= num || array[i];
				}
				fieldInfo.SetValue(map, array2);
				Plugin.Log.LogInfo((object)$"Grew Minimap.m_visibleIconTypes from {num} to {size}.");
			}
		}
	}
	[HarmonyPatch(typeof(Minimap), "Start")]
	internal static class Patch_Minimap_Start
	{
		private static void Postfix(Minimap __instance)
		{
			CustomIcons.Register(__instance);
			MapIconPicker.Build(__instance);
			PinStyles.RebuildOreTints();
		}
	}
	internal static class Fonts
	{
		private static readonly FieldInfo NameInputField = AccessTools.Field(typeof(Minimap), "m_nameInput");

		private static TMP_FontAsset _font;

		private static bool _warned;

		public static TMP_FontAsset Game
		{
			get
			{
				if ((Object)(object)_font != (Object)null)
				{
					return _font;
				}
				_font = FromMap() ?? AnyLoaded();
				if ((Object)(object)_font == (Object)null && !_warned)
				{
					_warned = true;
					Plugin.Log.LogWarning((object)"No TMP font asset found - this mod's labels will not draw.");
				}
				return _font;
			}
		}

		public static TextMeshProUGUI AddLabel(GameObject go)
		{
			TMP_FontAsset game = Game;
			if ((Object)(object)game == (Object)null)
			{
				return go.AddComponent<TextMeshProUGUI>();
			}
			bool activeSelf = go.activeSelf;
			go.SetActive(false);
			TextMeshProUGUI obj = go.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj).font = game;
			go.SetActive(activeSelf);
			return obj;
		}

		private static TMP_FontAsset FromMap()
		{
			if ((Object)(object)Minimap.instance == (Object)null || NameInputField == null)
			{
				return null;
			}
			object? value = NameInputField.GetValue(Minimap.instance);
			object? obj = ((value is TMP_InputField) ? value : null);
			if (obj == null)
			{
				return null;
			}
			TMP_Text textComponent = ((TMP_InputField)obj).textComponent;
			if (textComponent == null)
			{
				return null;
			}
			return textComponent.font;
		}

		private static TMP_FontAsset AnyLoaded()
		{
			TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
			foreach (TMP_FontAsset val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}
	}
	internal static class IconDrawer
	{
		private const int Columns = 10;

		private const int Cell = 34;

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

		public static void Draw(ConfigEntryBase entry)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			string item = entry.Definition.Section + "/" + entry.Definition.Key;
			PinIcon pinIcon = (PinIcon)entry.BoxedValue;
			Sprite[] sprites = CustomIcons.Sprites;
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			DrawIcon(GUILayoutUtility.GetRect(34f, 34f, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(34f),
				GUILayout.Height(34f)
			}), sprites, (int)pinIcon);
			bool flag = Expanded.Contains(item);
			if (GUILayout.Button(pinIcon.ToString() + (flag ? "  ▲" : "  ▼"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(150f) }))
			{
				if (flag)
				{
					Expanded.Remove(item);
				}
				else
				{
					Expanded.Add(item);
				}
			}
			GUILayout.EndHorizontal();
			if (!Expanded.Contains(item))
			{
				GUILayout.EndVertical();
				return;
			}
			if (sprites == null || sprites.Length == 0)
			{
				GUILayout.Label("Icon sheet not loaded yet - close and reopen this screen.", Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				return;
			}
			if (GUILayout.Button("Default", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
			{
				entry.BoxedValue = PinIcon.Default;
				Expanded.Remove(item);
			}
			for (int i = 0; i < sprites.Length; i++)
			{
				if (i % 10 == 0)
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				}
				Rect rect = GUILayoutUtility.GetRect(34f, 34f, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(34f),
					GUILayout.Height(34f)
				});
				if (GUI.Button(rect, GUIContent.none))
				{
					entry.BoxedValue = (PinIcon)i;
					Expanded.Remove(item);
				}
				DrawIcon(rect, sprites, i, i != (int)pinIcon);
				if (i % 10 == 9 || i == sprites.Length - 1)
				{
					GUILayout.EndHorizontal();
				}
			}
			GUILayout.EndVertical();
		}

		private static void DrawIcon(Rect slot, Sprite[] sprites, int index, bool dim = false)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			if (sprites != null && index >= 0 && index < sprites.Length)
			{
				Sprite val = sprites[index];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.texture == (Object)null))
				{
					Color color = GUI.color;
					GUI.color = (Color)(dim ? new Color(1f, 1f, 1f, 0.5f) : Color.white);
					Rect textureRect = val.textureRect;
					GUI.DrawTextureWithTexCoords(slot, (Texture)(object)val.texture, new Rect(((Rect)(ref textureRect)).x / (float)((Texture)val.texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)val.texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)val.texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)val.texture).height));
					GUI.color = color;
				}
			}
		}
	}
	internal static class IconGrid
	{
		public const float CellSize = 46f;

		public const float Spacing = 4f;

		public static readonly Color Resting = new Color(0.95f, 0.94f, 0.9f, 0.7f);

		public static readonly Color Selected = new Color(1f, 0.78f, 0.25f, 1f);

		public static readonly Color Hovered = new Color(1f, 1f, 1f, 1f);

		private static Sprite _border;

		private static Sprite _disc;

		public static Sprite Border => BorderSprite();

		public static float PanelHeight(float rows)
		{
			return rows * 50f + 24f;
		}

		public static float PanelWidth(int columns)
		{
			return (float)columns * 50f + 24f;
		}

		public static bool PointerOver(GameObject panel, RectTransform rect, Camera camera)
		{
			//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)
			if ((Object)(object)panel == (Object)null || (Object)(object)rect == (Object)null || !panel.activeInHierarchy)
			{
				return false;
			}
			return RectTransformUtility.RectangleContainsScreenPoint(rect, Vector2.op_Implicit(ZInput.pointerPosition), camera);
		}

		public static Camera CameraFor(GameObject panel)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			Canvas val = (((Object)(object)panel != (Object)null) ? panel.GetComponentInParent<Canvas>() : null);
			if (!((Object)(object)val != (Object)null) || (int)val.renderMode == 0)
			{
				return null;
			}
			return val.worldCamera;
		}

		public static List<Image> Build(GameObject panel, GameObject template, int columns, Action<int> onClick, float top = 0f, float bottom = 0f)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Viewport");
			val.transform.SetParent(panel.transform, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.offsetMin = new Vector2(8f, 8f + bottom);
			val2.offsetMax = new Vector2(-8f, -8f - top);
			val.AddComponent<RectMask2D>();
			GameObject val3 = new GameObject("Content");
			val3.transform.SetParent(val.transform, false);
			RectTransform val4 = val3.AddComponent<RectTransform>();
			val4.anchorMin = new Vector2(0f, 1f);
			val4.anchorMax = new Vector2(1f, 1f);
			val4.pivot = new Vector2(0f, 1f);
			VerticalLayoutGroup obj = val3.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).spacing = 6f;
			val3.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			ScrollRect obj2 = panel.AddComponent<ScrollRect>();
			obj2.content = val4;
			obj2.viewport = val2;
			obj2.horizontal = false;
			obj2.vertical = true;
			obj2.movementType = (MovementType)2;
			obj2.scrollSensitivity = 300f;
			List<Image> list = new List<Image>(CustomIcons.PickerCount);
			Transform parent = AddSection(val3.transform, columns);
			for (int i = 0; i < CustomIcons.Count; i++)
			{
				list.Add(CreateButton(parent, template, i, onClick));
			}
			if (CustomIcons.LegacyCount > 0)
			{
				AddHeading(val3.transform, "PREVIOUS ICON SET");
				Transform parent2 = AddSection(val3.transform, columns);
				for (int j = CustomIcons.Count; j < CustomIcons.PickerCount; j++)
				{
					list.Add(CreateButton(parent2, template, j, onClick));
				}
			}
			return list;
		}

		private static Transform AddSection(Transform parent, int columns)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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)
			//IL_001e: 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_0044: 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)
			GameObject val = new GameObject("Section");
			val.transform.SetParent(parent, false);
			val.AddComponent<RectTransform>();
			GridLayoutGroup obj = val.AddComponent<GridLayoutGroup>();
			obj.cellSize = new Vector2(46f, 46f);
			obj.spacing = new Vector2(4f, 4f);
			obj.constraint = (Constraint)0;
			val.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			return val.transform;
		}

		private static void AddHeading(Transform parent, string text)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Heading");
			val.transform.SetParent(parent, false);
			val.AddComponent<RectTransform>();
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredHeight = 18f;
			obj.flexibleWidth = 1f;
			TextMeshProUGUI obj2 = Fonts.AddLabel(val);
			((TMP_Text)obj2).text = text;
			((TMP_Text)obj2).fontSize = 12f;
			((Graphic)obj2).color = new Color(0.95f, 0.92f, 0.82f, 0.6f);
			((TMP_Text)obj2).alignment = (TextAlignmentOptions)514;
			((Graphic)obj2).raycastTarget = false;
		}

		public static void SetSelected(Image border, bool selected)
		{
			//IL_0014: 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 ((Object)(object)border != (Object)null)
			{
				((Graphic)border).color = (selected ? Selected : Resting);
			}
		}

		private static Sprite BorderSprite()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_00a0: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_border != (Object)null)
			{
				return _border;
			}
			Texture2D val = new Texture2D(8, 8, (TextureFormat)4, false);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(1f, 1f, 1f, 0f);
			for (int i = 0; i < 8; i++)
			{
				for (int j = 0; j < 8; j++)
				{
					bool flag = j == 0 || i == 0 || j == 7 || i == 7;
					val.SetPixel(j, i, flag ? Color.white : val2);
				}
			}
			((Texture)val).filterMode = (FilterMode)0;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			val.Apply();
			_border = Sprite.Create(val, new Rect(0f, 0f, 8f, 8f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(2f, 2f, 2f, 2f));
			return _border;
		}

		public static Sprite Disc()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_006c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_disc != (Object)null)
			{
				return _disc;
			}
			Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(15.5f, 15.5f);
			for (int i = 0; i < 32; i++)
			{
				for (int j = 0; j < 32; j++)
				{
					float num = Vector2.Distance(new Vector2((float)j, (float)i), val2);
					float num2 = Mathf.Clamp01(15f - num);
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num2));
				}
			}
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			val.Apply();
			_disc = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f));
			return _disc;
		}

		private static Image CreateButton(Transform parent, GameObject template, int index, Action<int> onClick)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00e3: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: 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_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Expected O, but got Unknown
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Expected O, but got Unknown
			GameObject val;
			if ((Object)(object)template != (Object)null)
			{
				val = Object.Instantiate<GameObject>(template, parent);
				((Object)val).name = $"CarturIcon_{index}";
				Image[] componentsInChildren = val.GetComponentsInChildren<Image>(true);
				foreach (Image val2 in componentsInChildren)
				{
					if ((Object)(object)((Component)val2).gameObject != (Object)(object)val)
					{
						((Behaviour)val2).enabled = false;
					}
				}
			}
			else
			{
				val = new GameObject($"CarturIcon_{index}");
				val.transform.SetParent(parent, false);
				val.AddComponent<RectTransform>();
				val.AddComponent<Image>();
			}
			Image component = val.GetComponent<Image>();
			if ((Object)(object)component != (Object)null)
			{
				component.sprite = null;
				((Graphic)component).color = new Color(0.07f, 0.08f, 0.08f, 0.85f);
				((Behaviour)component).enabled = true;
			}
			GameObject val3 = new GameObject("Icon");
			val3.transform.SetParent(val.transform, false);
			RectTransform obj = val3.AddComponent<RectTransform>();
			obj.anchorMin = Vector2.zero;
			obj.anchorMax = Vector2.one;
			obj.offsetMin = new Vector2(5f, 5f);
			obj.offsetMax = new Vector2(-5f, -5f);
			Image obj2 = val3.AddComponent<Image>();
			obj2.sprite = CustomIcons.SpriteForPicker(index);
			((Graphic)obj2).color = Color.white;
			obj2.preserveAspect = true;
			((Graphic)obj2).raycastTarget = false;
			GameObject val4 = new GameObject("Border");
			val4.transform.SetParent(val.transform, false);
			RectTransform obj3 = val4.AddComponent<RectTransform>();
			obj3.anchorMin = Vector2.zero;
			obj3.anchorMax = Vector2.one;
			obj3.offsetMin = Vector2.zero;
			obj3.offsetMax = Vector2.zero;
			Image val5 = val4.AddComponent<Image>();
			val5.sprite = BorderSprite();
			val5.type = (Type)1;
			((Graphic)val5).color = Resting;
			((Graphic)val5).raycastTarget = false;
			val.AddComponent<CellHover>().Bind(val5);
			Button obj4 = val.GetComponent<Button>() ?? val.AddComponent<Button>();
			obj4.onClick = new ButtonClickedEvent();
			int captured = index;
			((UnityEvent)obj4.onClick).AddListener((UnityAction)delegate
			{
				onClick(captured);
			});
			return val5;
		}

		public static GameObject FindTemplateButton(Minimap map)
		{
			Image[] array = (Image[])(object)new Image[4] { map.m_selectedIcon0, map.m_selectedIcon1, map.m_selectedIcon2, map.m_selectedIconBoss };
			foreach (Image val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).transform.parent != (Object)null)
				{
					return ((Component)((Component)val).transform.parent).gameObject;
				}
			}
			return null;
		}
	}
	internal static class LabelCrowding
	{
		private const float RevealRadius = 60f;

		private static readonly List<PinNameData> Shown = new List<PinNameData>();

		private static readonly List<PinData> Ordered = new List<PinData>();

		private static readonly Dictionary<string, int> NameCounts = new Dictionary<string, int>();

		private static readonly Comparison<PinData> ByRarity = delegate(PinData a, PinData b)
		{
			NameCounts.TryGetValue(a.m_name ?? string.Empty, out var value);
			NameCounts.TryGetValue(b.m_name ?? string.Empty, out var value2);
			return value.CompareTo(value2);
		};

		public static void Apply(List<PinData> pins)
		{
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			Shown.Clear();
			Ordered.Clear();
			NameCounts.Clear();
			if (!Plugin.ShowPinLabels.Value)
			{
				HideAll(pins);
				return;
			}
			float value = Plugin.HideLabelsFromZoom.Value;
			if (value < 100f && Crowding.ZoomOutPercent() > value)
			{
				HideAll(pins);
				return;
			}
			HideOutOfSight(pins);
			if (!Plugin.HideCollidingLabels.Value && !PinFilter.Active)
			{
				return;
			}
			foreach (PinData pin in pins)
			{
				PinNameData val = pin?.m_NamePinData;
				if (!((Object)(object)((val != null) ? val.PinNameRectTransform : null) == (Object)null) && !((Object)(object)val.PinNameGameObject == (Object)null) && val.PinNameGameObject.activeInHierarchy && !string.IsNullOrEmpty(pin.m_name))
				{
					if (!PinFilter.Matches(pin.m_name))
					{
						val.PinNameGameObject.SetActive(false);
						continue;
					}
					NameCounts.TryGetValue(pin.m_name, out var value2);
					NameCounts[pin.m_name] = value2 + 1;
					Ordered.Add(pin);
				}
			}
			if (Ordered.Count == 0)
			{
				return;
			}
			Ordered.Sort(ByRarity);
			Vector2 val2 = CursorIn(Ordered[0].m_iconElement);
			foreach (PinData item in Ordered)
			{
				PinNameData namePinData = item.m_NamePinData;
				Rect mine = RectOf(namePinData.PinNameRectTransform);
				if (((Object)(object)item.m_iconElement != (Object)null && Vector2.Distance(((Graphic)item.m_iconElement).rectTransform.anchoredPosition, val2) < 60f) || !Collides(mine))
				{
					Shown.Add(namePinData);
				}
				else
				{
					namePinData.PinNameGameObject.SetActive(false);
				}
			}
		}

		private static void HideOutOfSight(List<PinData> pins)
		{
			foreach (PinData pin in pins)
			{
				if (Crowding.OutOfSight(pin))
				{
					PinNameData val = pin?.m_NamePinData;
					if (!((Object)(object)((val != null) ? val.PinNameGameObject : null) == (Object)null) && val.PinNameGameObject.activeInHierarchy)
					{
						val.PinNameGameObject.SetActive(false);
					}
				}
			}
		}

		private static void HideAll(List<PinData> pins)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = CursorNear(pins);
			foreach (PinData pin in pins)
			{
				PinNameData val2 = pin?.m_NamePinData;
				if (!((Object)(object)((val2 != null) ? val2.PinNameGameObject : null) == (Object)null) && val2.PinNameGameObject.activeInHierarchy && (Crowding.OutOfSight(pin) || !((Object)(object)pin.m_iconElement != (Object)null) || !(Vector2.Distance(((Graphic)pin.m_iconElement).rectTransform.anchoredPosition, val) < 60f)))
				{
					val2.PinNameGameObject.SetActive(false);
				}
			}
		}

		private static Vector2 CursorNear(List<PinData> pins)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			foreach (PinData pin in pins)
			{
				if ((Object)(object)pin?.m_iconElement != (Object)null)
				{
					return CursorIn(pin.m_iconElement);
				}
			}
			return new Vector2(float.MaxValue, float.MaxValue);
		}

		private static bool Collides(Rect mine)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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)
			foreach (PinNameData item in Shown)
			{
				if ((Object)(object)item.PinNameRectTransform != (Object)null)
				{
					Rect val = RectOf(item.PinNameRectTransform);
					if (((Rect)(ref val)).Overlaps(mine))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static Vector2 CursorIn(Image icon)
		{
			//IL_0030: 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_0059: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)(((Object)(object)icon != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val == (Object)null)
			{
				return new Vector2(float.MaxValue, float.MaxValue);
			}
			Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>();
			Camera val2 = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null);
			Vector2 result = default(Vector2);
			if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(val, Vector2.op_Implicit(ZInput.pointerPosition), val2, ref result))
			{
				return new Vector2(float.MaxValue, float.MaxValue);
			}
			return result;
		}

		private static Rect RectOf(RectTransform rt)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			Vector2 anchoredPosition = rt.anchoredPosition;
			Rect rect = rt.rect;
			Vector2 size = ((Rect)(ref rect)).size;
			return new Rect(anchoredPosition.x - size.x * 0.5f, anchoredPosition.y - size.y * 0.5f, size.x, size.y);
		}
	}
	internal static class Labels
	{
		private static readonly string[] DropSuffixes = new string[4] { "ore", "scrap", "new", "old" };

		private static readonly HashSet<string> SpawnerNoise = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
		{
			"respawn", "night", "noarcher", "noise", "rise", "sleeping", "wakeup", "event", "bossroom", "stared",
			"surprise", "location", "random", "hildir", "meadows", "mountains", "mountain", "swamp", "forest", "ashlands",
			"deep", "north", "cave"
		};

		private static readonly HashSet<string> PlaceWords = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "nest", "pile", "heart", "core", "spawner", "totem", "stand", "hole" };

		private static readonly Dictionary<string, string> SpawnerAliases = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			{ "Hole", "Greydwarf Spawner" },
			{ "Elite", "Greydwarf Elite Spawner" },
			{ "Shaman", "Greydwarf Shaman Spawner" }
		};

		public static string ForOre(string prefabName)
		{
			if (PinCatalog.OreQualifiedBy.TryGetValue(prefabName, out var value) && !string.IsNullOrEmpty(value))
			{
				int num = value.IndexOf(" (via ");
				string text = StripSuffix((num > 0) ? value.Substring(0, num) : value);
				if (!string.IsNullOrEmpty(text))
				{
					return Prettify(text);
				}
			}
			return Prettify(StripOrePrefabNoise(prefabName));
		}

		public static string Localize(string text)
		{
			if (!string.IsNullOrEmpty(text) && Localization.instance != null)
			{
				return Localization.instance.Localize(text);
			}
			return text;
		}

		public static string ForPin(string label)
		{
			return StripRichText(Localize(label)) ?? string.Empty;
		}

		public static string StripRichText(string text)
		{
			if (string.IsNullOrEmpty(text) || text.IndexOf('<') < 0)
			{
				return text;
			}
			StringBuilder stringBuilder = new StringBuilder(text.Length);
			int num = 0;
			foreach (char c in text)
			{
				switch (c)
				{
				case '<':
					num++;
					break;
				case '>':
					if (num > 0)
					{
						num--;
					}
					break;
				default:
					if (num == 0)
					{
						stringBuilder.Append(c);
					}
					break;
				}
			}
			string text2 = stringBuilder.ToString().Trim();
			if (text2.Length <= 0)
			{
				return text;
			}
			return text2;
		}

		public static string ForLocation(string prefabName)
		{
			return Prettify(prefabName);
		}

		public static string ForLoreStone(string prefabName)
		{
			string text = Prettify(prefabName.StartsWith("Runestone_", StringComparison.OrdinalIgnoreCase) ? prefabName.Substring("Runestone_".Length) : prefabName);
			if (!string.IsNullOrEmpty(text))
			{
				return text + " Runestone";
			}
			return Prettify(prefabName);
		}

		public static string ForSpawner(string prefabName)
		{
			return CleanSpawnerLabel(Prettify(StripSpawnerPrefix(prefabName)));
		}

		public static string CleanSpawnerLabel(string prettified)
		{
			if (string.IsNullOrEmpty(prettified))
			{
				return prettified;
			}
			string[] array = prettified.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			List<string> list = new List<string>(array.Length);
			string[] array2 = array;
			foreach (string item in array2)
			{
				if (!SpawnerNoise.Contains(item))
				{
					list.Add(item);
				}
			}
			if (list.Count == 0)
			{
				return prettified;
			}
			string text = string.Join(" ", list.ToArray());
			if (SpawnerAliases.TryGetValue(text, out var value))
			{
				return value;
			}
			if (!PlaceWords.Contains(list[list.Count - 1]))
			{
				return text + " Spawner";
			}
			return text;
		}

		private static string StripSpawnerPrefix(string name)
		{
			string[] array = new string[2] { "Spawner_", "Spawn_" };
			foreach (string text in array)
			{
				if (name.StartsWith(text, StringComparison.OrdinalIgnoreCase))
				{
					return name.Substring(text.Length);
				}
			}
			return name;
		}

		private static string StripSuffix(string name)
		{
			string text = name.ToLowerInvariant();
			string[] dropSuffixes = DropSuffixes;
			foreach (string text2 in dropSuffixes)
			{
				if (text.Length > text2.Length && text.EndsWith(text2))
				{
					return name.Substring(0, name.Length - text2.Length);
				}
			}
			return name;
		}

		private static string StripOrePrefabNoise(string name)
		{
			string text = name;
			string[] array = new string[5] { "MineRock_", "rock1_", "rock2_", "rock3_", "rock4_" };
			foreach (string text2 in array)
			{
				if (text.StartsWith(text2, StringComparison.OrdinalIgnoreCase))
				{
					text = text.Substring(text2.Length);
					break;
				}
			}
			return text;
		}

		public static string Prettify(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return raw;
			}
			string text = raw.Replace('_', ' ');
			string[] array = new string[4] { "Mistlands ", "Ashlands ", "Hildir ", "Dvergr " };
			foreach (string text2 in array)
			{
				if (text.StartsWith(text2, StringComparison.OrdinalIgnoreCase) && text.Length > text2.Length)
				{
					text = text.Substring(text2.Length);
				}
			}
			StringBuilder stringBuilder = new StringBuilder(text.Length + 8);
			for (int j = 0; j < text.Length; j++)
			{
				char c = text[j];
				if (j > 0 && char.IsUpper(c) && !char.IsUpper(text[j - 1]) && text[j - 1] != ' ')
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(c);
			}
			text = stringBuilder.ToString();
			text = text.TrimEnd(Array.Empty<char>());
			int num = text.Length;
			while (num > 0 && (char.IsDigit(text[num - 1]) || text[num - 1] == ' '))
			{
				num--;
			}
			if (num > 0)
			{
				text = text.Substring(0, num);
			}
			string[] array2 = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			StringBuilder stringBuilder2 = new StringBuilder();
			array = array2;
			foreach (string text3 in array)
			{
				if (stringBuilder2.Length > 0)
				{
					stringBuilder2.Append(' ');
				}
				stringBuilder2.Append(char.ToUpperInvariant(text3[0]));
				if (text3.Length > 1)
				{
					stringBuilder2.Append(text3.Substring(1));
				}
			}
			if (stringBuilder2.Length <= 0)
			{
				return raw;
			}
			return stringBuilder2.ToString();
		}
	}
	internal static class LegacyIconNames
	{
		public const int LegacyBase = 1000;

		private static readonly Dictionary<string, int> Mapped = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
		{
			{ "MineFace", 119 },
			{ "CobwebArch", 39 },
			{ "Shrine", 42 },
			{ "Bee", 78 },
			{ "TreasureChest", 72 },
			{ "Nest", 9 },
			{ "Coins", 88 },
			{ "SerpentHead", 50 },
			{ "Ember", 85 },
			{ "Bed", 70 },
			{ "Boar", 138 },
			{ "Pig", 138 },
			{ "SkullAndBones", 80 },
			{ "Skull", 80 },
			{ "TrollSkull", 21 },
			{ "Crystal", 117 },
			{ "Campfire", 74 },
			{ "Castle", 40 },
			{ "Fort", 40 },
			{ "TowerDoor", 40 },
			{ "LockedTower", 40 },
			{ "FortressAssault", 36 },
			{ "Golem", 28 },
			{ "DragonEgg", 8 },
			{ "DrakeHead", 8 },
			{ "Pickaxe", 119 },
			{ "OreCluster", 119 },
			{ "Boulder", 119 },
			{ "Longship", 150 },
			{ "SailingBoat", 151 },
			{ "DvergrHead", 37 },
			{ "StandingStone", 57 },
			{ "Berries", 90 },
			{ "House", 43 },
			{ "LogCabin", 43 },
			{ "Village", 42 },
			{ "FulingFace", 3 },
			{ "TotemPole", 3 },
			{ "Banner", 4 },
			{ "OpenChest", 152 },
			{ "MysteryBox", 84 },
			{ "Tombstone", 2 },
			{ "Gravestone", 2 },
			{ "WizardHat", 62 },
			{ "SkeletalHand", 1 },
			{ "SwordAndSpear", 52 },
			{ "SwordAndShovel", 52 },
			{ "SinkingShip", 47 },
			{ "Tick", 26 },
			{ "GiantSkull", 51 },
			{ "MineTower", 34 },
			{ "Antlers", 137 },
			{ "SeekerHead", 5 },
			{ "Door", 39 },
			{ "StoneArch", 134 },
			{ "BrickWall", 134 },
			{ "CrossedSticks", 0 },
			{ "Blob", 16 },
			{ "Talon", 12 },
			{ "Arrowhead", 108 },
			{ "Swimmer", 136 },
			{ "DiveArrow", 86 },
			{ "Tree", 53 },
			{ "MushroomTree", 95 },
			{ "Leaf", 107 },
			{ "Sprout", 109 },
			{ "Pillars", 45 },
			{ "Imp", 27 },
			{ "Fish", 139 },
			{ "FishBones", 139 },
			{ "Hide", 145 },
			{ "Rubble", 127 },
			{ "Island", 55 }
		};

		private static readonly Dictionary<string, int> KeptOld = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
		{
			{ "Dot", 0 },
			{ "Bell", 14 },
			{ "Tent", 13 },
			{ "Chicken", 19 },
			{ "Signpost", 26 },
			{ "SignBoard", 82 },
			{ "Chalice", 44 },
			{ "NeedleAndThread", 60 },
			{ "Armour", 78 },
			{ "Canoe", 81 }
		};

		private static readonly Dictionary<int, string> LegacyNames = BuildLegacyNames();

		private static readonly Dictionary<string, string> Raw = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		private static Dictionary<int, string> BuildLegacyNames()
		{
			Dictionary<int, string> dictionary = new Dictionary<int, string>();
			foreach (KeyValuePair<string, int> item in KeptOld)
			{
				dictionary[1000 + item.Value] = item.Key;
			}
			return dictionary;
		}

		public static PinIcon? Translate(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			if (Mapped.TryGetValue(name, out var value))
			{
				return (PinIcon)value;
			}
			if (KeptOld.TryGetValue(name, out var value2))
			{
				return (PinIcon)(1000 + value2);
			}
			return null;
		}

		public static string NameFor(PinIcon icon)
		{
			if (!LegacyNames.TryGetValue((int)icon, out var value))
			{
				return null;
			}
			return value;
		}

		public static void Capture(string configPath)
		{
			Raw.Clear();
			if (string.IsNullOrEmpty(configPath) || !File.Exists(configPath))
			{
				return;
			}
			try
			{
				string text = string.Empty;
				string[] array = File.ReadAllLines(configPath);
				for (int i = 0; i < array.Length; i++)
				{
					string text2 = array[i].Trim();
					if (text2.Length == 0 || text2[0] == '#')
					{
						continue;
					}
					if (text2[0] == '[' && text2[text2.Length - 1] == ']')
					{
						text = text2.Substring(1, text2.Length - 2);
						continue;
					}
					int num = text2.IndexOf('=');
					if (num > 0)
					{
						Raw[text + "/" + text2.Substring(0, num).Trim()] = text2.Substring(num + 1).Trim();
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not read the config file to carry 1.2.2's icon names over: " + ex.Message));
			}
		}

		public static void Adopt(ConfigEntry<PinIcon> entry)
		{
			if (entry == null)
			{
				return;
			}
			string text = ((ConfigEntryBase)entry).Definition.Section + "/" + ((ConfigEntryBase)entry).Definition.Key;
			if (Raw.TryGetValue(text, out var value))
			{
				PinIcon? pinIcon = Translate(value);
				if (pinIcon.HasValue && entry.Value != pinIcon.Value)
				{
					entry.Value = pinIcon.Value;
					Plugin.Log.LogInfo((object)(text + ": '" + value + "' is from 1.2.2's sheet - carried over as " + Describe(pinIcon.Value) + "."));
				}
			}
		}

		private static string Describe(PinIcon icon)
		{
			if (icon < (PinIcon)1000)
			{
				return icon.ToString();
			}
			return "its original icon from the old sheet (" + NameFor(icon) + ")";
		}
	}
	internal static class MapIconPicker
	{
		private const float PanelWidth = 263f;

		private const float PanelHeight = 273f;

		private const int Columns = 4;

		private static GameObject _panel;

		private static RectTransform _panelRect;

		private static Camera _canvasCamera;

		private static readonly List<Image> _highlights = new List<Image>();

		private static MethodInfo _selectIcon;

		private static FieldInfo _selectedType;

		private const float CaptionHeight = 20f;

		private const float HandleSize = 12f;

		private static GameObject _searchBar;

		private static readonly FieldInfo PinUpdateRequired = AccessTools.Field(typeof(Minimap), "m_pinUpdateRequired");

		private static readonly FieldInfo NameInputField = AccessTools.Field(typeof(Minimap), "m_nameInput");

		private static MethodInfo _closestPinToCursor;

		public static bool PointerOverPanel()
		{
			return IconGrid.PointerOver(_panel, _panelRect, _canvasCamera);
		}

		public static void Build(Minimap map)
		{
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: 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)
			if ((Object)(object)_panel != (Object)null || (Object)(object)map == (Object)null || !Plugin.MapPickerEnabled.Value || !CustomIcons.Ready || (Object)(object)map.m_largeRoot == (Object)null)
			{
				return;
			}
			_selectIcon = AccessTools.Method(typeof(Minimap), "SelectIcon", new Type[1] { typeof(PinType) }, (Type[])null);
			_selectedType = AccessTools.Field(typeof(Minimap), "m_selectedType");
			_closestPinToCursor = AccessTools.Method(typeof(Minimap), "GetClosestPinToCursor", (Type[])null, (Type[])null);
			if (_selectIcon == null || _selectedType == null)
			{
				Plugin.Log.LogWarning((object)"Minimap.SelectIcon/m_selectedType not found - map icon picker disabled.");
				return;
			}
			_panel = new GameObject("CarturIconPicker");
			_panel.transform.SetParent(map.m_largeRoot.transform, false);
			RectTransform obj = (_panelRect = _panel.AddComponent<RectTransform>());
			obj.anchorMin = new Vector2(1f, 0f);
			obj.anchorMax = new Vector2(1f, 0f);
			obj.pivot = new Vector2(1f, 0f);
			obj.sizeDelta = new Vector2(263f, 273f);
			obj.anchoredPosition = new Vector2(0f - Plugin.MapPickerRight.Value, Plugin.MapPickerBottom.Value);
			((Graphic)_panel.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.55f);
			_canvasCamera = IconGrid.CameraFor(_panel);
			AddCaption(_panel);
			AddDragHandle(_panel);
			BuildSearchBar(map);
			_highlights.Clear();
			_highlights.AddRange(IconGrid.Build(_panel, IconGrid.FindTemplateButton(map), 4, delegate(int index)
			{
				Select(map, index);
			}, 20f));
			if (_selectedType.GetValue(map) is PinType type)
			{
				int num = CustomIcons.PickerIndexFor(type);
				for (int num2 = 0; num2 < _highlights.Count; num2++)
				{
					IconGrid.SetSelected(_highlights[num2], num2 == num);
				}
			}
			ClampToScreen();
			Plugin.Log.LogInfo((object)$"Map icon picker built with {CustomIcons.Count} icons plus {CustomIcons.LegacyCount} from the old sheet.");
		}

		private static void AddCaption(GameObject panel)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_008f: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Caption");
			val.transform.SetParent(panel.transform, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0f, 1f);
			obj.anchorMax = new Vector2(1f, 1f);
			obj.pivot = new Vector2(0.5f, 1f);
			obj.offsetMin = new Vector2(22f, -20f);
			obj.offsetMax = new Vector2(-22f, -2f);
			TextMeshProUGUI obj2 = Fonts.AddLabel(val);
			((TMP_Text)obj2).text = "SHIFT CLICK ICON TO CHANGE";
			((TMP_Text)obj2).fontSize = 14f;
			((Graphic)obj2).color = new Color(0.95f, 0.92f, 0.82f, 0.85f);
			((TMP_Text)obj2).alignment = (TextAlignmentOptions)514;
			((Graphic)obj2).raycastTarget = false;
		}

		private static void AddDragHandle(GameObject panel)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_008a: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("DragHandle");
			val.transform.SetParent(panel.transform, false);
			RectTransform obj = val.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0f, 1f);
			obj.anchorMax = new Vector2(0f, 1f);
			obj.pivot = new Vector2(0f, 1f);
			obj.sizeDelta = new Vector2(12f, 12f);
			obj.anchoredPosition = new Vector2(5f, -4f);
			Image obj2 = val.AddComponent<Image>();
			((Graphic)obj2).color = IconGrid.Selected;
			((Graphic)obj2).raycastTarget = true;
			val.AddComponent<PanelDrag>().Init(_panelRect, CommitPosition);
			val.AddComponent<CellHover>();
		}

		private static void CommitPosition()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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)
			if (!((Object)(object)_panelRect == (Object)null))
			{
				ClampToScreen();
				Vector2 anchoredPosition = _panelRect.anchoredPosition;
				Plugin.MapPickerRight.Value = 0f - anchoredPosition.x;
				Plugin.MapPickerBottom.Value = anchoredPosition.y;
			}
		}

		private static void ClampToScreen()
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			_panelRect.GetWorldCorners(array);
			float x = array[0].x;
			float x2 = array[2].x;
			float y = array[2].y;
			float num = 0f;
			float num2 = 0f;
			if (x2 > (float)Screen.width)
			{
				num -= x2 - (float)Screen.width;
			}
			if (x + num < 0f)
			{
				num += 0f - (x + num);
			}
			if (y > (float)Screen.height)
			{
				num2 -= y - (float)Screen.height;
			}
			if (y + num2 < 20f)
			{
				num2 += 20f - (y + num2);
			}
			if (num != 0f || num2 != 0f)
			{
				RectTransform panelRect = _panelRect;
				((Transform)panelRect).position = ((Transform)panelRect).position + new Vector3(num, num2, 0f);
			}
		}

		private static void BuildSearchBar(Minimap map)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Expected O, but got Unknown
			if ((Object)(object)_searchBar != (Object)null || (Object)(object)map.m_largeRoot == (Object)null)
			{
				return;
			}
			object? obj = NameInputField?.GetValue(map);
			TMP_InputField val = (TMP_InputField)((obj is TMP_InputField) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Minimap.m_nameInput not found - the pin search box is disabled.");
				return;
			}
			_searchBar = new GameObject("CarturPinSearch");
			_searchBar.transform.SetParent(map.m_largeRoot.transform, false);
			RectTransform obj2 = _searchBar.AddComponent<RectTransform>();
			obj2.anchorMin = new Vector2(0.5f, 1f);
			obj2.anchorMax = new Vector2(0.5f, 1f);
			obj2.pivot = new Vector2(0.5f, 1f);
			obj2.sizeDelta = new Vector2(340f, 30f);
			obj2.anchoredPosition = new Vector2(0f, -16f);
			((Graphic)_searchBar.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.6f);
			TMP_InputField obj3 = Object.Instantiate<TMP_InputField>(val, _searchBar.transform);
			((Object)((Component)obj3).gameObject).name = "CarturPinFilter";
			((Component)obj3).gameObject.SetActive(true);
			RectTransform component = ((Component)obj3).GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = new Vector2(6f, 3f);
			component.offsetMax = new Vector2(-6f, -3f);
			obj3.text = string.Empty;
			Graphic placeholder = obj3.placeholder;
			TMP_Text val2 = (TMP_Text)(object)((placeholder is TMP_Text) ? placeholder : null);
			if (val2 != null)
			{
				val2.text = "Search pins...";
			}
			obj3.onValueChanged = new OnChangeEvent();
			obj3.onEndEdit = new SubmitEvent();
			((UnityEvent<string>)(object)obj3.onValueChanged).AddListener((UnityAction<string>)delegate(string text)
			{
				PinFilter.Text = text;
				PinUpdateRequired?.SetValue(map, true);
			});
			TextFocus.Register(obj3);
			TextFocus.DropVanillaSubmit(obj3);
		}

		private static void Select(Minimap map, int index)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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)
			PinType val = CustomIcons.TypeForPicker(index);
			_selectIcon.Invoke(map, new object[1] { val });
			for (int i = 0; i < _highlights.Count; i++)
			{
				IconGrid.SetSelected(_highlights[i], i == index);
			}
		}

		public static bool TryEditPinUnderCursor(Minimap map)
		{
			if ((Object)(object)map == (Object)null || _closestPinToCursor == null)
			{
				return false;
			}
			if (!ZInput.GetKey((KeyCode)304, false) && !ZInput.GetKey((KeyCode)303, false))
			{
				return false;
			}
			object? obj = _closestPinToCursor.Invoke(map, null);
			PinData val = Editable(map, (PinData)((obj is PinData) ? obj : null));
			if (val == null)
			{
				PinEditor.Close();
				return false;
			}
			PinEditor.Open(map, val);
			return true;
		}

		private static PinData Editable(Minimap map, PinData pin)
		{
			//IL_0042: 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_004d: 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_0054: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			if (pin == null || pin.m_save)
			{
				return pin;
			}
			List<PinData> pins = MinimapAccess.GetPins(map);
			if (pins == null)
			{
				return null;
			}
			PinData result = null;
			float num = 64f;
			foreach (PinData item in pins)
			{
				if (item != null && item.m_save)
				{
					Vector3 val = item.m_pos - pin.m_pos;
					float num2 = val.x * val.x + val.z * val.z;
					if (!(num2 > num))
					{
						num = num2;
						result = item;
					}
				}
			}
			return result;
		}

		public static void ClearHighlightsIfVanilla(PinType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (CustomIcons.IsCustom(type))
			{
				return;
			}
			foreach (Image highlight in _highlights)
			{
				if ((Object)(object)highlight != (Object)null)
				{
					((Behaviour)highlight).enabled = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Minimap), "OnMapLeftClick")]
	internal static class Patch_Minimap_OnMapLeftClick
	{
		private static bool Prefix(Minimap __instance)
		{
			return !MapIconPicker.TryEditPinUnderCursor(__instance);
		}
	}
	[HarmonyPatch(typeof(Minimap), "SelectIcon")]
	internal static class Patch_Minimap_SelectIcon
	{
		private static void Postfix(PinType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			MapIconPicker.ClearHighlightsIfVanilla(type);
		}
	}
	[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
	internal static class Patch_ZInput_GetMouseScrollWheel
	{
		private static bool Prefix(ref float __result)
		{
			if (!MapIconPicker.PointerOverPanel() && !PinEditor.PointerOverPanel())
			{
				return true;
			}
			__result = 0f;
			return false;
		}
	}
	internal static class OreRegistry
	{
		private struct Node
		{
			public GameObject Go;

			public Vector3 Pos;
		}

		private static readonly List<Node> Seen = new List<Node>();

		public static void Add(GameObject go)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			for (int i = 0; i < Seen.Count; i++)
			{
				if ((Object)(object)Seen[i].Go == (Object)(object)go)
				{
					return;
				}
			}
			Seen.Add(new Node
			{
				Go = go,
				Pos = go.transform.position
			});
		}

		public static void Clear()
		{
			Seen.Clear();
		}

		public static IEnumerable<Vector3> AlivePositions()
		{
			for (int i = Seen.Count - 1; i >= 0; i--)
			{
				if ((Object)(object)Seen[i].Go == (Object)null)
				{
					Seen.RemoveAt(i);
				}
				else
				{
					yield return Seen[i].Pos;
				}
			}
		}

		public static bool NodeNear(Vector3 pos, float radius)
		{
			//IL_0045: 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_004b: 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_0051: 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_005e: 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)
			float num = radius * radius;
			bool result = false;
			for (int num2 = Seen.Count - 1; num2 >= 0; num2--)
			{
				if ((Object)(object)Seen[num2].Go == (Object)null)
				{
					Seen.RemoveAt(num2);
				}
				else
				{
					Vector3 val = Seen[num2].Pos - pos;
					if (val.x * val.x + val.z * val.z <= num)
					{
						result = true;
					}
				}
			}
			return result;
		}
	}
	internal class PanelDrag : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		private RectTransform _panel;

		private Canvas _canvas;

		private Action _commit;

		public void Init(RectTransform panel, Action commit)
		{
			_panel = panel;
			_commit = commit;
			_canvas = (((Object)(object)panel != (Object)null) ? ((Component)panel).GetComponentInParent<Canvas>() : null);
		}

		public void OnBeginDrag(PointerEventData eventData)
		{
		}

		public void OnDrag(PointerEventData eventData)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_panel == (Object)null))
			{
				float num = (((Object)(object)_canvas != (Object)null) ? _canvas.scaleFactor : 1f);
				if (num <= 0f)
				{
					num = 1f;
				}
				RectTransform panel = _panel;
				panel.anchoredPosition += eventData.delta / num;
			}
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			_commit?.Invoke();
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class Patch_ZNetScene_Awake
	{
		private static void Postfix(ZNetScene __instance)
		{
			PinCatalog.Build(__instance);
			PinPlacer.Clear();
			ChestRegistry.Clear();
			PinRecord.Unload();
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "AddInstance")]
	internal static class Patch_ZNetScene_AddInstance
	{
		private static int _seen;

		private static int _matched;

		private static int _enqueued;

		private static int _skippedHive;

		private static int _skippedPicked;

		private static int _skippedGroup;

		[Conditional("DIAGNOSTICS")]
		private static void Tally(ref int counter)
		{
			counter++;
		}

		private static void Postfix(ZDO zdo, ZNetView nview)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (!PinCatalog.Built || zdo == null || (Object)(object)nview == (Object)null)
			{
				return;
			}
			int prefab = zdo.GetPrefab();
			if (!PinCatalog.TryGet(prefab, out var category))
			{
				return;
			}
			switch (category)
			{
			case PinCategory.BossAltar:
				return;
			case PinCategory.Pickable:
				if (!Plugin.PickableGroupEnabled(PinCatalog.GroupOf(prefab)))
				{
					return;
				}
				break;
			}
			GameObject gameObject = ((Component)nview).gameObject;
			if (PinCatalog.PlayerBuildable(category) && !IsWild(zdo))
			{
				return;
			}
			if (category == PinCategory.Pickable)
			{
				Pickable component = gameObject.GetComponent<Pickable>();
				if ((Object)(object)component != (Object)null && !component.CanBePicked())
				{
					return;
				}
			}
			if (category == PinCategory.Chest)
			{
				ChestRegistry.Add(gameObject.GetComponent<Container>());
			}
			if (category == PinCategory.Ore)
			{
				OreRegistry.Add(gameObject);
			}
			PinPlacer.Enqueue(category, zdo.GetPosition(), gameObject, PinPlacer.SubtypeFor(category, prefab, gameObject));
		}

		private static bool IsWild(ZDO zdo)
		{
			return zdo.GetLong(ZDOVars.s_creator, 0L) == 0;
		}
	}
	[HarmonyPatch(typeof(Bed), "Interact")]
	internal static class Patch_Bed_Interact
	{
		private static void Postfix(Bed __instance)
		{
			//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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Game.instance == (Object)null)
			{
				return;
			}
			PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
			if (playerProfile != null && playerProfile.HaveCustomSpawnPoint())
			{
				Vector3 spawnPoint = __instance.GetSpawnPoint();
				Vector3 val = playerProfile.GetCustomSpawnPoint() - spawnPoint;
				if (!(((Vector3)(ref val)).sqrMagnitude > 0.01f))
				{
					PinPlacer.PinHome(spawnPoint, "Home");
				}
			}
		}
	}
	[HarmonyPatch(typeof(Minimap), "UpdatePins")]
	internal static class Patch_Minimap_UpdatePins
	{
		private static void Postfix(Minimap __instance)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Invalid comparison between Unknown and I4
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_010f: 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)
			List<PinData> pins = MinimapAccess.GetPins(__instance);
			if (pins == null)
			{
				return;
			}
			Crowding.Measure(pins);
			LabelCrowding.Apply(pins);
			foreach (PinData item in pins)
			{
				if ((Object)(object)item?.m_iconElement == (Object)null)
				{
					continue;
				}
				PinStyles.Style style = PinStyles.For(item.m_pos);
				if (PinFilter.Active && !PinFilter.Matches(item.m_name))
				{
					Color color = ((Graphic)item.m_iconElement).color;
					color.a = 0.15f;
					((Graphic)item.m_iconElement).color = color;
					continue;
				}
				if (!item.m_checked)
				{
					Color? val = PinStyles.ColourFor(style);
					Color colour;
					if (val.HasValue)
					{
						((Graphic)item.m_iconElement).color = val.Value;
					}
					else if (PinStyles.TintFor(item.m_type, out colour))
					{
						((Graphic)item.m_iconElement).color = colour;
					}
				}
				PinType val2 = PinPlacer.LootedChestType();
				if ((int)val2 != 8 && item.m_type == val2)
				{
					Color color2 = ((Graphic)item.m_iconElement).color;
					color2.a *= 0.5f;
					((Graphic)item.m_iconElement).color = color2;
				}
			}
		}
	}
	internal static class DiscoveryRequests
	{
		private static readonly Dictionary<string, string> ByPinName = new Dictionary<string, string>();

		public static void Record(string pinName, string locationName)
		{
			if (!string.IsNullOrEmpty(pinName))
			{
				ByPinName[pinName] = locationName;
			}
		}

		public static string BossFor(string pinName)
		{
			if (pinName == null || !ByPinName.TryGetValue(pinName, out var value))
			{
				return null;
			}
			string text = Subtypes.Match(Subtypes.Bosses, pinName, value);
			if (text == null)
			{
				Plugin.Log.LogInfo((object)("Revealed '" + value + "' as '" + pinName + "' - no boss matched, left to vanilla."));
			}
			return text;
		}
	}
	[HarmonyPatch(typeof(Game), "DiscoverClosestLocation")]
	internal static class Patch_Game_DiscoverClosestLocation
	{
		private static void Prefix(string name, string pinName)
		{
			DiscoveryRequests.Record(pinName, name);
		}
	}
	[HarmonyPatch(typeof(Minimap), "DiscoverLocation")]
	internal static class Patch_Minimap_DiscoverLocation
	{
		private const float SamePlace = 12f;

		private static bool Prefix(Minimap __instance, Vector3 pos, string name, bool showMap, ref bool __result)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return true;
			}
			string text = DiscoveryRequests.BossFor(name);
			if (text == null)
			{
				return true;
			}
			bool flag = PinRecord.HasCategoryNear(PinCategory.BossAltar, pos, 12f);
			if (!PinPlacer.PinDiscovered(text, pos, name))
			{
				return true;
			}
			if (flag)
			{
				if (showMap)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_pin_exist", 0, (Sprite)null, false);
					__instance.ShowPointOnMap(pos);
				}
				__result = false;
				return false;
			}
			((Character)Player.m_localPlayer).Message((MessageType)1, "$msg_pin_added: " + name, 0, (Sprite)null, false);
			if (showMap)
			{
				__instance.ShowPointOnMap(pos);
			}
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(Minimap), "UpdateLocationPins")]
	internal static class Patch_Minimap_UpdateLocationPins
	{
		[HarmonyPatch(typeof(TombStone), "GiveBoost")]
		internal static class Patch_TombStone_GiveBoost
		{
			private static bool Prepare()
			{
				if (AccessTools.Method(typeof(TombStone), "GiveBoost", (Type[])null, (Type[])null) != null)
				{
					return true;
				}
				Plugin.Log.LogWarning((object)"TombStone.GiveBoost not found - death pins will not clear themselves. Everything else still works.");
				return false;
			}

			private static void Prefix(TombStone __instance)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)__instance != (Object)null)
				{
					PinPlacer.ClearDeathPin(((Component)__instance).transform.position);
				}
			}
		}

		private static readonly FieldInfo LocationPins = AccessTools.Field(typeof(Minimap), "m_locationPins");

		private const float SamePlace = 12f;

		private static readonly PinCategory[] Replaced = new PinCategory[2]
		{
			PinCategory.BossAltar,
			PinCategory.Trader
		};

		private static void Postfix(Minimap __instance)
		{
			//IL_0069: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (!(LocationPins?.GetValue(__instance) is Dictionary<Vector3, PinData> { Count: not 0 } dictionary))
			{
				return;
			}
			List<Vector3> list = null;
			foreach (KeyValuePair<Vector3, PinData> item in dictionary)
			{
				PinCategory[] replaced = Replaced;
				foreach (PinCategory category in replaced)
				{
					Plugin.CategorySettings categorySettings = Plugin.SettingsFor(category);
					if (categorySettings != null && categorySettings.Enabled.Value && PinRecord.HasCategoryNear(category, item.Key, 12f))
					{
						(list ?? (list = new List<Vector3>())).Add(item.Key);
						break;
					}
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (Vector3 item2 in list)
			{
				__instance.RemovePin(dictionary[item2]);
				dictionary.Remove(item2);
			}
		}
	}
	public enum PinCategory
	{
		Ore,
		Dungeon,
		Camp,
		BossAltar,
		Beehive,
		Pickable,
		Runestone,
		LoreStone,
		Chest,
		Spawner,
		Leviathan,
		Trader,
		Wisp,
		Landmark,
		Prop,
		Miniboss,
		Home
	}
	public enum PickableGroup
	{
		HighValue,
		Berries,
		Mushrooms,
		Crops,
		Junk,
		Other
	}
	internal static class PinCatalog
	{
		private static readonly Dictionary<int, PinCategory> ByHash = new Dictionary<int, PinCategory>();

		private static readonly Dictionary<int, PickableGroup> PickableGroups = new Dictionary<int, PickableGroup>();

		private static readonly Dictionary<int, string> OreTypes = new Dictionary<int, string>();

		public static readonly Dictionary<PinCategory, List<string>> NamesByCategory = new Dictionary<PinCategory, List<string>>();

		public static readonly Dictionary<string, string> OreQualifiedBy = new Dictionary<string, string>();

		public static readonly (string Token, string Type)[] OreTokens = new(string, string)[12]
		{
			("copperore", "Copper"),
			("tinore", "Tin"),
			("ironore", "Iron"),
			("ironscrap", "Iron"),
			("silverore", "Silver"),
			("obsidian", "Obsidian"),
			("flametal", "Flametal"),
			("sulfur", "Sulfur"),
			("blackmarble", "Black Marble"),
			("softtissue", "Giant Remains"),
			("chitin", "Chitin"),
			("tar", "Tar")
		};

		public static bool Built { get; private set; }

		public static bool TryGet(int prefabHash, out PinCategory category)
		{
			return ByHash.TryGetValue(prefabHash, out category);
		}

		public static bool Contains(int hash)
		{
			return ByHash.ContainsKey(hash);
		}

		public static bool PlayerBuildable(PinCategory category)
		{
			if (category != PinCategory.Beehive && category != PinCategory.Chest)
			{
				return category == PinCategory.Prop;
			}
			return true;
		}

		public static PickableGroup GroupOf(int prefabHash)
		{
			if (!PickableGroups.TryGetValue(prefabHash, out var value))
			{
				return PickableGroup.Other;
			}
			return value;
		}

		public static string OreTypeOf(int prefabHash)
		{
			if (!OreTypes.TryGetValue(prefabHash, out var value))
			{
				return null;
			}
			return value;
		}

		public static void Build(ZNetScene scene)
		{
			ByHash.Clear();
			PickableGroups.Clear();
			OreTypes.Clear();
			NamesByCategory.Clear();
			OreQualifiedBy.Clear();
			if ((Object)(object)scene == (Object)null || scene.m_prefabs == null)
			{
				return;
			}
			Dictionary<PinCategory, int> dictionary = new Dictionary<PinCategory, int>();
			foreach (GameObject prefab in scene.m_prefabs)
			{
				if (!((Object)(object)prefab == (Object)null) && TryClassify(prefab, out var category))
				{
					int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name);
					ByHash[stableHashCode] = category;
					dictionary.TryGetValue(category, out var value);
					dictionary[category] = value + 1;
					if (!NamesByCategory.TryGetValue(category, out var value2))
					{
						value2 = new List<string>();
						NamesByCategory[category] = value2;
					}
					value2.Add(((Object)prefab).name);
					if (category == PinCategory.Pickable)
					{
						PickableGroups[stableHashCode] = ClassifyPickable(prefab);
					}
				}
			}
			Built = true;
			foreach (KeyValuePair<PinCategory, int> item in dictionary)
			{
				Plugin.Log.LogInfo((object)$"Catalog: {item.Value} {item.Key} prefabs");
			}
		}

		private static bool TryClassify(GameObject prefab, out PinCategory category)
		{
			if (Subtypes.Match(Subtypes.Props, ((Object)prefab).name) != null)
			{
				category = PinCategory.Prop;
				return true;
			}
			if ((Object)(object)prefab.GetComponent<OfferingBowl>() != (Object)null)
			{
				category = PinCategory.BossAltar;
				return true;
			}
			if ((Object)(object)prefab.GetComponent<BossStone>() != (Object)null)
			{
				category = PinCategory.Ore;
				return false;
			}
			if ((Object)(object)prefab.GetComponent<Vegvisir>() != (Object)null || (Object)(object)prefab.GetComponent<RuneStone>() != (Object)null)
			{
				category = PinCategory.Runestone;
				return true;
			}
			if ((Object)(object)prefab.GetComponent<Leviathan>() != (Object)null)
			{
				category = PinCategory.Leviathan;
				return true;
			}
			if ((Object)(object)prefab.GetComponent<Trader>() != (Object)null)
			{
				category = PinCategory.Trader;
				return true;
			}
			if ((Object)(object)prefab.GetComponent<WispSpawner>() != (Object)null)
			{
				category = PinCategory.Wisp;
				return true;
			}
			if ((Object)(object)prefab.GetComponent<SpawnArea>() != (Object)null || (Object)(object)prefab.GetComponent<CreatureSpawner>() != (Object)null)
			{
				category = ((Subtypes.Match(Subtypes.Minibosses, PinPlacer.SpawnedCreaturePrefabName(prefab)) != null) ? PinCategory.Miniboss : PinCategory.Spawner);
				return true;
			}
			Container component = prefab.GetComponent<Container>();
			if ((Object)(object)component != (Object)null && component.m_defaultItems?.m_drops != null && component.m_defaultItems.m_drops.Count > 0)
			{
				category = PinCategory.Chest;
				return true;
			}
			if (!LooksLikeFragment(((Object)prefab).name) && LooksMineable(prefab, out var how) && YieldsOre(prefab, out var via, out var oreType))
			{
				via = via + " [" + how + "]";
				category = PinCategory.Ore;
				OreQualifiedBy[((Object)prefab).name] = via;
				OreTypes[StringExtensionMethods.GetStableHashCode(((Object)prefab).name)] = oreType;
				return true;
			}
			if ((Object)(object)prefab.GetComponent<Beehive>() != (Object)null)
			{
				category = PinCategory.Beehive;
				return true;
			}
			if ((Object)(object)prefab.GetComponent<Pickable>() != (Object)null || (Object)(object)prefab.GetComponent<PickableItem>() != (Object)null)
			{
				category = PinCategory.Pickable;
				return true;
			}
			category = PinCategory.Ore;
			return false;
		}

		private static bool LooksMineable(GameObject prefab, out string how)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing refe