Decompiled source of OreFinder v1.2.0

plugins/OreFinder/OreFinder.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using OreFinder.Detection;
using OreFinder.Highlight;
using OreFinder.Hud;
using OreFinder.Map;
using Splatform;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("Egor Fadeev")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Finds ore veins, dungeon entrances, monster spawners, ancient roots and rare pickables around the player: a screen arrow with name and distance, a light beam and a map pin, once per find. Hotkey toggle, configurable radius and lists.")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+d282174cadfef8938378c708ee8e09e0db4cfd15")]
[assembly: AssemblyProduct("Ore Finder")]
[assembly: AssemblyTitle("OreFinder")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 OreFinder
{
	public sealed class Finder : MonoBehaviour
	{
		private readonly List<VeinHighlight> _highlights = new List<VeinHighlight>();

		private readonly HashSet<ZDOID> _seen = new HashSet<ZDOID>();

		private readonly List<Vector3> _seenPositions = new List<Vector3>();

		private const float SameVeinDistance = 0.5f;

		private readonly HashSet<ZDOID> _waitingForWishbone = new HashSet<ZDOID>();

		private readonly List<ZNetView> _nearby = new List<ZNetView>();

		private readonly List<Teleport> _entrances = new List<Teleport>();

		private const float LocationExtent = 50f;

		private TargetCatalog? _catalog;

		private string? _catalogSource;

		private float _nextScan;

		private bool _inWorld;

		private bool _overlayFailed;

		public int HighlightCount => _highlights.Count;

		public int SeenCount => _seenPositions.Count;

		private static int LocationProxyPrefab
		{
			get
			{
				ZoneSystem instance = ZoneSystem.instance;
				if (!((Object)(object)instance != (Object)null) || !((Object)(object)instance.m_locationProxyPrefab != (Object)null))
				{
					return 0;
				}
				return StringExtensionMethods.GetStableHashCode(((Object)instance.m_locationProxyPrefab).name);
			}
		}

		public void SetEnabled(bool enabled)
		{
			Plugin.Settings.Enabled.Value = enabled;
			if (!enabled)
			{
				RemoveHighlights();
			}
			ShowMessage((MessageType)2, enabled ? "Ore Finder: on" : "Ore Finder: off");
			Plugin.Log.LogInfo((object)(enabled ? "Enabled" : "Disabled"));
		}

		public void SetGroupEnabled(TargetGroup group, bool enabled)
		{
			ConfigEntry<bool> val = Plugin.Settings.SwitchFor(group);
			if (val != null)
			{
				val.Value = enabled;
				if (!enabled)
				{
					RemoveHighlights(group);
				}
				string text = TargetGroups.Label(group);
				ShowMessage((MessageType)2, "Ore Finder: " + text + " " + (enabled ? "on" : "off"));
				Plugin.Log.LogInfo((object)(text + " " + (enabled ? "enabled" : "disabled")));
			}
		}

		public int Reset()
		{
			int count = _seenPositions.Count;
			_seen.Clear();
			_seenPositions.Clear();
			_waitingForWishbone.Clear();
			RemoveHighlights();
			_nextScan = 0f;
			return count;
		}

		private void Awake()
		{
			((MonoBehaviour)this).useGUILayout = false;
		}

		private void Update()
		{
			//IL_005b: 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_00a8: 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)
			try
			{
				ModConfig settings = Plugin.Settings;
				if ((Object)(object)ZNetScene.instance == (Object)null)
				{
					if (_inWorld)
					{
						LeaveWorld();
					}
					return;
				}
				_inWorld = true;
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					if (_highlights.Count > 0)
					{
						RemoveHighlights();
					}
					return;
				}
				if (IsPressed(settings.ToggleKey.Value))
				{
					SetEnabled(!settings.Enabled.Value);
				}
				if (IsPressed(settings.OresToggleKey.Value))
				{
					SetGroupEnabled(TargetGroup.Ore, !settings.FindOres.Value);
				}
				if (IsPressed(settings.DungeonsToggleKey.Value))
				{
					SetGroupEnabled(TargetGroup.Dungeon, !settings.Dungeons.Value);
				}
				if (IsPressed(settings.SpawnersToggleKey.Value))
				{
					SetGroupEnabled(TargetGroup.Spawner, !settings.Spawners.Value);
				}
				if (!settings.Enabled.Value)
				{
					if (_highlights.Count > 0)
					{
						RemoveHighlights();
					}
					return;
				}
				UpdateHighlights();
				if (Time.time >= _nextScan)
				{
					_nextScan = Time.time + Mathf.Max(0.1f, settings.ScanInterval.Value);
					Scan(localPlayer, settings);
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Update failed, retrying in 5 s: {arg}");
				_nextScan = Time.time + 5f;
			}
		}

		private void OnGUI()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (_overlayFailed || _highlights.Count == 0)
			{
				return;
			}
			ModConfig settings = Plugin.Settings;
			if (!settings.Enabled.Value || !settings.ScreenMarker.Value || (int)Event.current.type != 7)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || Hud.IsUserHidden() || Minimap.IsOpen() || Menu.IsVisible())
			{
				return;
			}
			Camera mainCamera = Utils.GetMainCamera();
			if ((Object)(object)mainCamera == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)localPlayer).transform.position;
			try
			{
				MarkerOverlay.Draw(_highlights, mainCamera, position);
			}
			catch (Exception arg)
			{
				_overlayFailed = true;
				Plugin.Log.LogError((object)$"Screen markers disabled until restart: {arg}");
			}
		}

		private void OnDestroy()
		{
			RemoveHighlights();
		}

		private void Scan(Player player, ModConfig settings)
		{
			//IL_0019: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			TargetCatalog targetCatalog = CatalogFor(settings);
			_nearby.Clear();
			Vector3 position = ((Component)player).transform.position;
			float radius = Mathf.Max(settings.Radius.Value, settings.TargetRadius.Value);
			OreScanner.CollectNearby(position, radius, LocationProxyPrefab, settings.TargetRadius.Value + 50f, _nearby);
			bool? flag = null;
			foreach (ZNetView item in _nearby)
			{
				ZDOID uid = item.GetZDO().m_uid;
				if (_seen.Contains(uid))
				{
					continue;
				}
				LocationProxy component = ((Component)item).GetComponent<LocationProxy>();
				if ((Object)(object)component != (Object)null)
				{
					ScanLocation(item, component, targetCatalog, player, position, settings);
					continue;
				}
				TargetKind targetKind = targetCatalog.Classify(item);
				if (targetKind == null)
				{
					continue;
				}
				float num = ((targetKind.Group == TargetGroup.Ore) ? settings.Radius.Value : settings.TargetRadius.Value);
				Vector3 val = ((Component)item).transform.position - position;
				if (((Vector3)(ref val)).sqrMagnitude > num * num)
				{
					continue;
				}
				if (targetKind.Group == TargetGroup.Pickable)
				{
					Pickable component2 = ((Component)item).GetComponent<Pickable>();
					if ((Object)(object)component2 != (Object)null && component2.m_picked)
					{
						continue;
					}
				}
				if (targetKind.Hidden && settings.WishboneNeeded.Value != WishboneRule.NotNeeded)
				{
					bool valueOrDefault = flag == true;
					if (!flag.HasValue)
					{
						valueOrDefault = HasWishbone(player, settings);
						flag = valueOrDefault;
					}
					if (!flag.Value)
					{
						if (_waitingForWishbone.Add(uid))
						{
							Plugin.Debug(targetKind.DisplayName + " (" + Utils.GetPrefabName(((Component)item).gameObject) + ") is hidden and waits for the " + settings.WishboneItem.Value);
						}
						continue;
					}
				}
				_seen.Add(uid);
				Vector3 position2 = ((Component)item).transform.position;
				if (IsSeenVein(position2))
				{
					Plugin.Debug($"{targetKind.DisplayName} at {position2} is a vein already shown (new object after a hit), skipped");
					continue;
				}
				_seenPositions.Add(position2);
				try
				{
					Highlight(item, ((Component)item).gameObject, targetKind, player, settings);
				}
				catch (Exception arg)
				{
					Plugin.Log.LogError((object)$"Could not highlight {targetKind.DisplayName} ({Utils.GetPrefabName(((Component)item).gameObject)}): {arg}");
				}
			}
		}

		private void ScanLocation(ZNetView view, LocationProxy proxy, TargetCatalog catalog, Player player, Vector3 playerPosition, ModConfig settings)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (!catalog.Targets.Dungeons || !LocationEntrances.IsSpawned(proxy))
			{
				return;
			}
			_entrances.Clear();
			LocationEntrances.Collect(proxy, _entrances);
			bool flag = true;
			float value = settings.TargetRadius.Value;
			string text = null;
			foreach (Teleport entrance in _entrances)
			{
				Vector3 position = ((Component)entrance).transform.position;
				if (IsSeenVein(position))
				{
					continue;
				}
				Vector3 val = position - playerPosition;
				if (((Vector3)(ref val)).sqrMagnitude > value * value)
				{
					flag = false;
					continue;
				}
				if (text == null)
				{
					text = LocationEntrances.LocationName(view);
				}
				TargetKind targetKind = catalog.ClassifyEntrance(entrance, text);
				if (targetKind != null)
				{
					_seenPositions.Add(position);
					try
					{
						Highlight(view, ((Component)entrance).gameObject, targetKind, player, settings);
					}
					catch (Exception arg)
					{
						Plugin.Log.LogError((object)$"Could not highlight {targetKind.DisplayName} ({text}): {arg}");
					}
				}
			}
			if (flag)
			{
				_seen.Add(view.GetZDO().m_uid);
			}
		}

		private void Highlight(ZNetView view, GameObject target, TargetKind kind, Player player, ModConfig settings)
		{
			//IL_0023: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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)
			VeinHighlight veinHighlight = new VeinHighlight(view, target, kind, settings.ToHighlightOptions());
			_highlights.Add(veinHighlight);
			float num = Vector3.Distance(((Component)player).transform.position, veinHighlight.Position);
			if (settings.Message.Value)
			{
				ShowMessage((MessageType)1, $"{kind.DisplayName}: {num:0} m");
			}
			if (settings.MapPin.Value)
			{
				if (Character.InInterior(veinHighlight.Position))
				{
					Plugin.Debug("No map pin for " + kind.DisplayName + ": found inside a dungeon");
				}
				else if (!MapPins.TryAdd(veinHighlight.Position, kind.DisplayName, settings.MapPinSpacing.Value, PinIcons.ToPinType(settings.PinFor(kind.Group))))
				{
					Plugin.Debug($"No map pin for {kind.DisplayName}: another pin is within {settings.MapPinSpacing.Value:0.#} m");
				}
			}
			Plugin.Debug("Found " + kind.DisplayName + " (" + Utils.GetPrefabName(target) + ", key " + kind.Key + ") " + $"at {veinHighlight.Position}, {num:0.#} m away");
		}

		private void UpdateHighlights()
		{
			for (int num = _highlights.Count - 1; num >= 0; num--)
			{
				VeinHighlight veinHighlight = _highlights[num];
				if (veinHighlight.Expired)
				{
					veinHighlight.Remove();
					_highlights.RemoveAt(num);
				}
				else
				{
					veinHighlight.Update();
				}
			}
		}

		private void RemoveHighlights()
		{
			foreach (VeinHighlight highlight in _highlights)
			{
				highlight.Remove();
			}
			_highlights.Clear();
		}

		private void RemoveHighlights(TargetGroup group)
		{
			for (int num = _highlights.Count - 1; num >= 0; num--)
			{
				if (_highlights[num].Kind.Group == group)
				{
					_highlights[num].Remove();
					_highlights.RemoveAt(num);
				}
			}
		}

		private void LeaveWorld()
		{
			RemoveHighlights();
			_seen.Clear();
			_seenPositions.Clear();
			_waitingForWishbone.Clear();
			_catalog = null;
			_inWorld = false;
		}

		private static bool HasWishbone(Player player, ModConfig settings)
		{
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return false;
			}
			string text = OreFilter.Normalize(settings.WishboneItem.Value ?? string.Empty);
			if (text.Length == 0)
			{
				return false;
			}
			bool flag = settings.WishboneNeeded.Value == WishboneRule.Equipped;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (!flag || allItem.m_equipped)
				{
					string name = (((Object)(object)allItem.m_dropPrefab != (Object)null) ? ((Object)allItem.m_dropPrefab).name : string.Empty);
					string name2 = ((allItem.m_shared != null) ? allItem.m_shared.m_name : string.Empty);
					if (OreFilter.Normalize(name) == text || OreFilter.Normalize(name2) == text)
					{
						return true;
					}
				}
			}
			return false;
		}

		private bool IsSeenVein(Vector3 origin)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			foreach (Vector3 seenPosition in _seenPositions)
			{
				Vector3 val = seenPosition - origin;
				if (((Vector3)(ref val)).sqrMagnitude < 0.25f)
				{
					return true;
				}
			}
			return false;
		}

		private TargetCatalog CatalogFor(ModConfig settings)
		{
			string text = settings.CatalogSource();
			if (_catalog == null || _catalogSource != text)
			{
				OreNames oreNames = (settings.CustomNames.Value ? OreNames.Parse(settings.Names.Value) : null);
				_catalog = new TargetCatalog(OreFilter.Parse(settings.Ores.Value), settings.ToTargetOptions(), oreNames);
				_catalogSource = text;
				Plugin.Debug("Looking for ores: " + _catalog.Ores.Describe() + "; targets: " + _catalog.Targets.Describe() + "; names: " + ((oreNames != null) ? oreNames.Describe() : "from the game"));
			}
			return _catalog;
		}

		private static bool IsPressed(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0)
			{
				return false;
			}
			if (Console.IsVisible() || TextInput.IsVisible() || ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()))
			{
				return false;
			}
			if (!ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, false))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if (!ZInput.GetKey(modifier, false))
				{
					return false;
				}
			}
			return true;
		}

		private static void ShowMessage(MessageType type, string text)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			MessageHud instance = MessageHud.instance;
			if ((Object)(object)instance != (Object)null)
			{
				instance.ShowMessage(type, text, 0, (Sprite)null, false, true);
			}
		}
	}
	public sealed class ModConfig
	{
		private readonly ConfigFile _config;

		public ConfigEntry<bool> Enabled { get; }

		public ConfigEntry<KeyboardShortcut> ToggleKey { get; }

		public ConfigEntry<KeyboardShortcut> OresToggleKey { get; }

		public ConfigEntry<KeyboardShortcut> DungeonsToggleKey { get; }

		public ConfigEntry<KeyboardShortcut> SpawnersToggleKey { get; }

		public ConfigEntry<bool> IsDebug { get; }

		public ConfigEntry<float> Radius { get; }

		public ConfigEntry<float> ScanInterval { get; }

		public ConfigEntry<bool> FindOres { get; }

		public ConfigEntry<string> Ores { get; }

		public ConfigEntry<bool> Dungeons { get; }

		public ConfigEntry<bool> Roots { get; }

		public ConfigEntry<bool> Spawners { get; }

		public ConfigEntry<string> Pickables { get; }

		public ConfigEntry<string> Trees { get; }

		public ConfigEntry<float> TargetRadius { get; }

		public ConfigEntry<float> Duration { get; }

		public ConfigEntry<bool> ScreenMarker { get; }

		public ConfigEntry<bool> Beam { get; }

		public ConfigEntry<bool> Light { get; }

		public ConfigEntry<bool> Glow { get; }

		public ConfigEntry<bool> Message { get; }

		public ConfigEntry<WishboneRule> WishboneNeeded { get; }

		public ConfigEntry<string> WishboneItem { get; }

		public ConfigEntry<bool> CustomNames { get; }

		public ConfigEntry<string> Names { get; }

		public ConfigEntry<bool> MapPin { get; }

		public ConfigEntry<float> MapPinSpacing { get; }

		public ConfigEntry<PinIcon> OrePin { get; }

		public ConfigEntry<PinIcon> DungeonPin { get; }

		public ConfigEntry<PinIcon> SpawnerPin { get; }

		public ConfigEntry<PinIcon> OtherPin { get; }

		public ModConfig(ConfigFile config)
		{
			//IL_003f: 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)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Expected O, but got Unknown
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Expected O, but got Unknown
			_config = config;
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable the finder. The toggle key flips this setting in game and saves it.");
			ToggleKey = config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), "Key that turns the finder on and off in game. Modifiers are allowed, e.g. \"F9 + LeftControl\". Ignored while typing in the chat or the console.");
			OresToggleKey = config.Bind<KeyboardShortcut>("General", "OresToggleKey", KeyboardShortcut.Empty, "Key that turns the ore search (FindOres) on and off on its own, leaving the other targets as they are. Unset by default.");
			DungeonsToggleKey = config.Bind<KeyboardShortcut>("General", "DungeonsToggleKey", KeyboardShortcut.Empty, "Key that turns the dungeon entrance search (Dungeons) on and off on its own. Unset by default.");
			SpawnersToggleKey = config.Bind<KeyboardShortcut>("General", "SpawnersToggleKey", KeyboardShortcut.Empty, "Key that turns the spawner search (Spawners) on and off on its own. Unset by default.");
			IsDebug = config.Bind<bool>("General", "IsDebug", false, "Log every vein that is found, with its prefab and the item that made it count as ore.");
			Radius = config.Bind<float>("Detection", "Radius", 20f, new ConfigDescription("Search radius in metres around the player.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>()));
			ScanInterval = config.Bind<float>("Detection", "ScanInterval", 1f, new ConfigDescription("Seconds between two scans.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 30f), Array.Empty<object>()));
			FindOres = config.Bind<bool>("Detection", "FindOres", true, "Look for ores at all. Off = only the targets from the Targets section are found; the Ores list below still says which ores count. The console command 'orefinder ores on|off' and OresToggleKey flip this setting.");
			Ores = config.Bind<string>("Detection", "Ores", "", "Which ores to look for, comma-separated. Empty = every ore: any mineable object that drops an item whose name contains the word Ore or Scrap (copper, tin, silver, iron scrap piles, flametal). Otherwise list item names (CopperOre, TinOre, SilverOre, IronScrap, FlametalOre, FlametalOreNew, ...) or object prefab names (rock4_copper, silvervein, MineRock_Obsidian, ...). Plain rocks, obsidian and black marble are not ores and only show up when listed here.");
			Dungeons = config.Bind<bool>("Targets", "Dungeons", true, "Find the entrances of crypts, caves and mines: any door with an Enter prompt (burial chambers, sunken crypts, troll caves, frost caves, infested mines, ...).");
			Roots = config.Bind<bool>("Targets", "Roots", true, "Find ancient roots (the sap extractor spots in the Mistlands).");
			Spawners = config.Bind<bool>("Targets", "Spawners", true, "Find monster spawners: greydwarf nests, evil bone piles, body piles and the like, plus the invisible spawn points that respawn their creature (surtling spawners at fire geysers, ...). Spawn points that fire only once are skipped.");
			Pickables = config.Bind<string>("Targets", "Pickables", "Pickable_DragonEgg, Pickable_Mushroom_JotunPuffs, Pickable_Mushroom_Magecap, Pickable_Fiddlehead, Pickable_VoltureEgg", "Pickables to find, by the object's prefab name (Pickable_DragonEgg, Pickable_Mushroom_JotunPuffs, Pickable_Mushroom_Magecap, Pickable_Fiddlehead, Pickable_VoltureEgg, Pickable_Thistle, CloudberryBush, Pickable_BogIronOre, ...) or by the item it gives (DragonEgg, Thistle, Cloudberry, ...), comma-separated. Already picked ones are skipped until they regrow. Empty = none.");
			Trees = config.Bind<string>("Targets", "Trees", "", "Trees to find, by the wood they drop (YggdrasilWood, Blackwood, Frostwood, ElderBark, FineWood, ...), comma-separated. Empty = none.");
			TargetRadius = config.Bind<float>("Targets", "TargetRadius", 40f, new ConfigDescription("Search radius in metres for everything except ores (Radius is for ores).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>()));
			Duration = config.Bind<float>("Highlight", "Duration", 10f, new ConfigDescription("Seconds a newly found vein stays highlighted. Every vein is highlighted once; use the console command 'orefinder reset' to forget the veins already shown.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), Array.Empty<object>()));
			ScreenMarker = config.Bind<bool>("Highlight", "ScreenMarker", true, "Draw an arrow with the ore name and distance on the screen: over the vein while it is in view, at the screen edge pointing towards it otherwise.");
			Beam = config.Bind<bool>("Highlight", "Beam", true, "Draw a vertical light beam above the vein.");
			Light = config.Bind<bool>("Highlight", "Light", true, "Light up the vein and the ground around it with a coloured, pulsing light.");
			Glow = config.Bind<bool>("Highlight", "Glow", true, "Tint the vein's own material with an emissive glow. Only works for materials whose shader has an emission colour.");
			Message = config.Bind<bool>("Highlight", "Message", true, "Show a message in the top-left corner with the ore name and distance when a vein is found.");
			WishboneNeeded = config.Bind<WishboneRule>("Hidden", "WishboneNeeded", WishboneRule.InInventory, "Hidden ores are the ones the game marks for the Wishbone: silver veins and the scrap piles with a beacon. InInventory: found only while the Wishbone is anywhere in your inventory. Equipped: only while it is equipped, like the game's own finder. NotNeeded: always found. Hidden veins skipped for lack of the Wishbone are found later once you carry it.");
			WishboneItem = config.Bind<string>("Hidden", "WishboneItem", "Wishbone", "Item that counts as the Wishbone, by prefab name or $item_ name. Change it for a modded finder item.");
			CustomNames = config.Bind<bool>("Names", "CustomNames", false, "Show your own names from the Names setting instead of the game's names (Copper deposit, Silver vein, ...) in the screen marker, the message and the map pin.");
			Names = config.Bind<string>("Names", "Names", "CopperOre=C, TinOre=T, SilverOre=S, IronScrap=I, FlametalOre=F, FlametalOreNew=F, GoldOre=B, Obsidian=O, Pickable_Mushroom_Magecap=Mc, Pickable_Fiddlehead=Fh, $item_ancientroot=YR", "Your names as key=name pairs separated by commas. The key is the ore item (CopperOre, GoldOre, ...), the pickable's prefab or item (Pickable_DragonEgg, DragonEgg), the wood of a tree (YggdrasilWood), a dungeon's location key ($location_forestcrypt), a spawner's prefab (Spawner_GreydwarfNest) or the object prefab (rock4_copper, silvervein). Targets without a pair get the initials of their name (Burial Chambers = BC, Dragon egg = DE, Magecap = Ma). Only used when CustomNames is on.");
			MapPin = config.Bind<bool>("Map", "MapPin", true, "Add a dot pin named after the ore to the map when a vein is found. The pin is saved with your map like one you placed yourself.");
			MapPinSpacing = config.Bind<float>("Map", "MapPinSpacing", 10f, new ConfigDescription("Do not add a pin when any other pin (yours, the mod's, a death marker, ...) is within this many metres. 0 = always add.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			OrePin = config.Bind<PinIcon>("Map", "OrePin", PinIcon.Dot, "Map pin icon for ores.");
			DungeonPin = config.Bind<PinIcon>("Map", "DungeonPin", PinIcon.House, "Map pin icon for dungeon entrances.");
			SpawnerPin = config.Bind<PinIcon>("Map", "SpawnerPin", PinIcon.Hammer, "Map pin icon for spawners.");
			OtherPin = config.Bind<PinIcon>("Map", "OtherPin", PinIcon.Dot, "Map pin icon for roots, pickables and trees.");
		}

		public ConfigEntry<bool>? SwitchFor(TargetGroup group)
		{
			return (ConfigEntry<bool>?)(group switch
			{
				TargetGroup.Ore => FindOres, 
				TargetGroup.Dungeon => Dungeons, 
				TargetGroup.Root => Roots, 
				TargetGroup.Spawner => Spawners, 
				_ => null, 
			});
		}

		public PinIcon PinFor(TargetGroup group)
		{
			return group switch
			{
				TargetGroup.Ore => OrePin.Value, 
				TargetGroup.Dungeon => DungeonPin.Value, 
				TargetGroup.Spawner => SpawnerPin.Value, 
				_ => OtherPin.Value, 
			};
		}

		public TargetOptions ToTargetOptions()
		{
			return new TargetOptions
			{
				Ores = FindOres.Value,
				Dungeons = Dungeons.Value,
				Roots = Roots.Value,
				Spawners = Spawners.Value,
				Pickables = NameList.Parse(Pickables.Value),
				Trees = NameList.Parse(Trees.Value)
			};
		}

		public string CatalogSource()
		{
			return string.Join("\n", FindOres.Value, Ores.Value, Dungeons.Value, Roots.Value, Spawners.Value, Pickables.Value, Trees.Value, CustomNames.Value, CustomNames.Value ? Names.Value : string.Empty);
		}

		public void Reload()
		{
			_config.Reload();
		}

		public HighlightOptions ToHighlightOptions()
		{
			return new HighlightOptions(Duration.Value, Beam.Value, Light.Value, Glow.Value);
		}

		public string Describe()
		{
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			string text = OreFilter.Parse(Ores.Value).Describe();
			return (Enabled.Value ? "enabled" : "disabled") + ", radius " + Radius.Value.ToString("0.#", invariantCulture) + " m for ores, " + TargetRadius.Value.ToString("0.#", invariantCulture) + " m for the rest, scan every " + ScanInterval.Value.ToString("0.##", invariantCulture) + " s, targets: " + ToTargetOptions().Describe() + ", ore list: " + text + ", highlight " + Duration.Value.ToString("0.#", invariantCulture) + " s, map pins " + (MapPin.Value ? "on" : "off") + ", names " + (CustomNames.Value ? OreNames.Parse(Names.Value).Describe() : "from the game") + ", hidden ores " + ((WishboneNeeded.Value == WishboneRule.NotNeeded) ? "always" : ("need " + WishboneItem.Value + " " + ((WishboneNeeded.Value == WishboneRule.Equipped) ? "equipped" : "in the inventory"))) + ", " + $"toggle key {ToggleKey.Value}";
		}
	}
	[BepInPlugin("muindor.OreFinder", "Ore Finder", "1.2.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private Harmony? _harmony;

		public static ManualLogSource Log { get; private set; }

		public static ModConfig Settings { get; private set; }

		public static Finder? Finder { get; private set; }

		private void Awake()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Settings = new ModConfig(((BaseUnityPlugin)this).Config);
			Finder = ((Component)this).gameObject.AddComponent<Finder>();
			_harmony = new Harmony("muindor.OreFinder");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)("Ore Finder 1.2.0 loaded: " + Settings.Describe()));
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		public static void Debug(string message)
		{
			if (Settings != null && Settings.IsDebug.Value)
			{
				Log.LogInfo((object)message);
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "muindor.OreFinder";

		public const string PLUGIN_NAME = "Ore Finder";

		public const string PLUGIN_VERSION = "1.2.0";
	}
}
namespace OreFinder.Patches
{
	[HarmonyPatch(typeof(Terminal), "InitTerminal")]
	internal static class Terminal_InitTerminal_Patch
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static ConsoleEvent <0>__Execute;
		}

		private const string Command = "orefinder";

		private static readonly string Usage = "orefinder [status|on|off|reset|reload|" + string.Join("|", TargetGroups.SwitchWords) + " [on|off]]";

		private static void Postfix()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			string text = Usage + " - control Ore Finder: show the settings, turn it on or off, forget the veins already shown, reload the config, or turn one group of targets on or off (no on/off = flip it)";
			object obj = <>O.<0>__Execute;
			if (obj == null)
			{
				ConsoleEvent val = Execute;
				<>O.<0>__Execute = val;
				obj = (object)val;
			}
			new ConsoleCommand("orefinder", text, (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		private static void Execute(ConsoleEventArgs args)
		{
			Terminal context = args.Context;
			string text = ((args.Args.Length > 1) ? args.Args[1].ToLowerInvariant() : "status");
			Finder finder = Plugin.Finder;
			if (TargetGroups.TryParse(text, out var group))
			{
				SwitchGroup(context, finder, group, (args.Args.Length > 2) ? args.Args[2].ToLowerInvariant() : null);
				return;
			}
			switch (text)
			{
			case "on":
			case "off":
				if ((Object)(object)finder != (Object)null)
				{
					finder.SetEnabled(text == "on");
					context.AddString("Ore Finder: " + text);
				}
				break;
			case "reset":
			{
				int num = (((Object)(object)finder != (Object)null) ? finder.Reset() : 0);
				context.AddString(string.Format("{0}: forgot {1} veins, they will be highlighted again", "Ore Finder", num));
				break;
			}
			case "reload":
				Plugin.Settings.Reload();
				context.AddString("Ore Finder: config reloaded, " + Plugin.Settings.Describe());
				break;
			case "status":
			{
				string text2 = (((Object)(object)finder != (Object)null) ? $", {finder.HighlightCount} highlighted now, {finder.SeenCount} found in this world" : string.Empty);
				context.AddString("Ore Finder 1.2.0: " + Plugin.Settings.Describe() + text2);
				break;
			}
			default:
				context.AddString("Usage: " + Usage);
				break;
			}
		}

		private static void SwitchGroup(Terminal terminal, Finder? finder, TargetGroup group, string? state)
		{
			ConfigEntry<bool> val = Plugin.Settings.SwitchFor(group);
			if (val == null)
			{
				terminal.AddString("Usage: " + Usage);
				return;
			}
			bool flag;
			if (state != null && (state == null || state.Length != 0))
			{
				if (!(state == "on"))
				{
					if (!(state == "off"))
					{
						terminal.AddString("Usage: " + Usage);
						return;
					}
					flag = false;
				}
				else
				{
					flag = true;
				}
			}
			else
			{
				flag = !val.Value;
			}
			if ((Object)(object)finder != (Object)null)
			{
				finder.SetGroupEnabled(group, flag);
			}
			else
			{
				val.Value = flag;
			}
			terminal.AddString("Ore Finder: " + TargetGroups.Label(group) + " " + (flag ? "on" : "off"));
		}
	}
}
namespace OreFinder.Map
{
	internal static class MapPins
	{
		public static bool TryAdd(Vector3 position, string name, float spacing, PinType type)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			if (spacing > 0f)
			{
				foreach (PinData pin in instance.m_pins)
				{
					if (!IsTransient(pin.m_type) && Utils.DistanceXZ(pin.m_pos, position) < spacing)
					{
						return false;
					}
				}
			}
			instance.AddPin(position, type, name, true, false, 0L, default(PlatformUserID));
			return true;
		}

		private static bool IsTransient(PinType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			if ((int)type != 10 && (int)type != 7 && (int)type != 12 && (int)type != 11)
			{
				return (int)type == 13;
			}
			return true;
		}
	}
	public enum PinIcon
	{
		Fire,
		House,
		Hammer,
		Dot,
		Portal
	}
	public static class PinIcons
	{
		public static PinType ToPinType(PinIcon icon)
		{
			return (PinType)(icon switch
			{
				PinIcon.Fire => 0, 
				PinIcon.House => 1, 
				PinIcon.Hammer => 2, 
				PinIcon.Portal => 6, 
				_ => 3, 
			});
		}
	}
}
namespace OreFinder.Hud
{
	internal static class MarkerOverlay
	{
		private const int ArrowTextureSize = 48;

		private const float ArrowSize = 36f;

		private const float EdgeMargin = 56f;

		private static Texture2D? _arrow;

		private static GUIStyle? _label;

		public static void Draw(IReadOnlyList<VeinHighlight> highlights, Camera camera, Vector3 playerPosition)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: 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_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Event.current.type != 7)
			{
				return;
			}
			Texture2D arrow = _arrow ?? (_arrow = CreateArrow(48));
			GUIStyle val = _label ?? (_label = CreateLabelStyle());
			float num = Screen.width;
			float num2 = Screen.height;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(num / 2f, num2 / 2f);
			Vector2 val6 = default(Vector2);
			Vector2 val7 = default(Vector2);
			foreach (VeinHighlight highlight in highlights)
			{
				Vector3 val3 = camera.WorldToViewportPoint(highlight.Position);
				ScreenMarker screenMarker = ScreenMarkerMath.Compute(val3.x, val3.y, val3.z, num, num2, 56f);
				float alpha = highlight.Alpha;
				Color color = highlight.Kind.Color;
				color.a = alpha;
				float num3 = Vector3.Distance(playerPosition, highlight.Position);
				GUIContent val4 = new GUIContent($"{highlight.Kind.DisplayName}  {num3:0} m");
				Vector2 val5 = val.CalcSize(val4);
				if (screenMarker.OnScreen)
				{
					((Vector2)(ref val6))..ctor(screenMarker.X, screenMarker.Y - 10f);
					DrawArrow(arrow, val6, screenMarker.AngleDegrees, color);
					DrawLabel(val, val4, val5, new Vector2(val6.x, val6.y - 36f - 8f - val5.y / 2f), alpha);
					continue;
				}
				((Vector2)(ref val7))..ctor(screenMarker.X, screenMarker.Y);
				DrawArrow(arrow, val7, screenMarker.AngleDegrees, color);
				Vector2 val8 = val2 - val7;
				Vector2 normalized = ((Vector2)(ref val8)).normalized;
				float num4 = 44f + Mathf.Abs(normalized.x) * val5.x / 2f + Mathf.Abs(normalized.y) * val5.y / 2f;
				DrawLabel(val, val4, val5, val7 + normalized * num4, alpha);
			}
		}

		private static void DrawArrow(Texture2D arrow, Vector2 tip, float angle, Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			Matrix4x4 matrix = GUI.matrix;
			Color color2 = GUI.color;
			GUIUtility.RotateAroundPivot(angle, tip);
			float num = 45f;
			GUI.color = new Color(0f, 0f, 0f, 0.7f * color.a);
			GUI.DrawTexture(new Rect(tip.x - num / 2f, tip.y - (num - 36f) / 2f, num, num), (Texture)(object)arrow);
			GUI.color = color;
			GUI.DrawTexture(new Rect(tip.x - 18f, tip.y, 36f, 36f), (Texture)(object)arrow);
			GUI.color = color2;
			GUI.matrix = matrix;
		}

		private static void DrawLabel(GUIStyle style, GUIContent content, Vector2 size, Vector2 center, float alpha)
		{
			//IL_0002: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(center.x - size.x / 2f, center.y - size.y / 2f, size.x, size.y);
			Color color = GUI.color;
			GUI.color = new Color(0f, 0f, 0f, alpha);
			GUI.Label(new Rect(((Rect)(ref val)).x + 1f, ((Rect)(ref val)).y + 1f, ((Rect)(ref val)).width, ((Rect)(ref val)).height), content, style);
			GUI.color = new Color(1f, 1f, 1f, alpha);
			GUI.Label(val, content, style);
			GUI.color = color;
		}

		private static GUIStyle CreateLabelStyle()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				fontSize = 16,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4,
				wordWrap = false
			};
			val.normal.textColor = Color.white;
			return val;
		}

		private static Texture2D CreateArrow(int size)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(size, size, (TextureFormat)4, false)
			{
				hideFlags = (HideFlags)61,
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1,
				name = "OreFinder arrow"
			};
			float num = (float)size / 2f;
			float num2 = (float)size - 1f;
			float num3 = 1f;
			float num4 = (float)size / 2f - 1f;
			Color32[] array = (Color32[])(object)new Color32[size * size];
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					int num5 = 0;
					for (int k = 0; k < 2; k++)
					{
						for (int l = 0; l < 2; l++)
						{
							float num6 = (float)j + 0.25f + (float)l * 0.5f;
							float num7 = (float)i + 0.25f + (float)k * 0.5f;
							float num8 = (num7 - num3) / (num2 - num3);
							float num9 = num4 * (1f - num8);
							if (num7 >= num3 && num7 <= num2 && Mathf.Abs(num6 - num) <= num9)
							{
								num5++;
							}
						}
					}
					byte b = (byte)(num5 * 255 / 4);
					array[i * size + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, b);
				}
			}
			val.SetPixels32(array);
			val.Apply(false, true);
			return val;
		}
	}
	public readonly struct ScreenMarker
	{
		public float X { get; }

		public float Y { get; }

		public float AngleDegrees { get; }

		public bool OnScreen { get; }

		public ScreenMarker(float x, float y, float angleDegrees, bool onScreen)
		{
			X = x;
			Y = y;
			AngleDegrees = angleDegrees;
			OnScreen = onScreen;
		}
	}
	public static class ScreenMarkerMath
	{
		private const float Epsilon = 0.0001f;

		public static ScreenMarker Compute(float vx, float vy, float vz, float width, float height, float margin)
		{
			bool flag = !IsBad(vx) && !IsBad(vy) && !IsBad(vz);
			bool flag2 = vz > 0f;
			if (flag && flag2 && vx >= 0f && vx <= 1f && vy >= 0f && vy <= 1f)
			{
				return new ScreenMarker(vx * width, (1f - vy) * height, 180f, onScreen: true);
			}
			float num = width / 2f;
			float num2 = height / 2f;
			float num3 = 0f;
			float num4 = 1f;
			if (flag)
			{
				num3 = vx * width - num;
				num4 = (1f - vy) * height - num2;
				if (!flag2)
				{
					num3 = 0f - num3;
					num4 = 0f - num4;
				}
				if (Math.Abs(num3) < 0.0001f && Math.Abs(num4) < 0.0001f)
				{
					num3 = 0f;
					num4 = 1f;
				}
			}
			float num5 = Math.Max(1f, num - margin);
			float num6 = Math.Max(1f, num2 - margin);
			float num7 = float.MaxValue;
			if (Math.Abs(num3) > 0.0001f)
			{
				num7 = Math.Min(num7, num5 / Math.Abs(num3));
			}
			if (Math.Abs(num4) > 0.0001f)
			{
				num7 = Math.Min(num7, num6 / Math.Abs(num4));
			}
			float angleDegrees = (float)(Math.Atan2(num3, 0f - num4) * 180.0 / Math.PI);
			return new ScreenMarker(num + num3 * num7, num2 + num4 * num7, angleDegrees, onScreen: false);
		}

		private static bool IsBad(float value)
		{
			if (!float.IsNaN(value))
			{
				return float.IsInfinity(value);
			}
			return true;
		}
	}
}
namespace OreFinder.Highlight
{
	public readonly struct HighlightOptions
	{
		public float Duration { get; }

		public bool Beam { get; }

		public bool Light { get; }

		public bool Glow { get; }

		public HighlightOptions(float duration, bool beam, bool light, bool glow)
		{
			Duration = duration;
			Beam = beam;
			Light = light;
			Glow = glow;
		}
	}
	public sealed class VeinHighlight
	{
		private const float BeamHeight = 30f;

		private const float LightIntensity = 5f;

		private const float FadeFraction = 0.25f;

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

		private static readonly string[] BeamShaders = new string[5] { "Sprites/Default", "UI/Default", "Hidden/Internal-Colored", "Particles/Standard Unlit", "Legacy Shaders/Particles/Alpha Blended" };

		private static Material? _beamMaterial;

		private static bool _beamMaterialSearched;

		private readonly ZNetView _view;

		private readonly float _start;

		private readonly float _duration;

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

		private GameObject? _root;

		private Light? _light;

		private LineRenderer? _beam;

		public ZDOID Id { get; }

		public TargetKind Kind { get; }

		public Vector3 Position { get; }

		public bool Expired
		{
			get
			{
				if (!((Object)(object)_view == (Object)null))
				{
					return Time.time - _start >= _duration;
				}
				return true;
			}
		}

		public float Alpha => Mathf.Clamp01((_duration - (Time.time - _start)) / (_duration * 0.25f));

		private static Material? BeamMaterial
		{
			get
			{
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_004f: Expected O, but got Unknown
				if (_beamMaterialSearched)
				{
					return _beamMaterial;
				}
				_beamMaterialSearched = true;
				string[] beamShaders = BeamShaders;
				foreach (string text in beamShaders)
				{
					Shader val = Shader.Find(text);
					if (!((Object)(object)val == (Object)null))
					{
						_beamMaterial = new Material(val)
						{
							hideFlags = (HideFlags)61,
							name = "OreFinder beam"
						};
						ConfigureTransparent(_beamMaterial);
						Plugin.Debug("Beam shader: " + text);
						return _beamMaterial;
					}
				}
				Plugin.Log.LogWarning((object)"No shader available for the beam; the beam is disabled. The light, glow and screen marker still work.");
				return null;
			}
		}

		public VeinHighlight(ZNetView view, GameObject target, TargetKind kind, HighlightOptions options)
		{
			//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_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)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			_view = view;
			Kind = kind;
			Id = view.GetZDO().m_uid;
			_start = Time.time;
			_duration = Mathf.Max(0.5f, options.Duration);
			bool found;
			Bounds val = BoundsOf(target, out found);
			Position = (found ? ((Bounds)(ref val)).center : target.transform.position);
			float extent = (found ? Mathf.Max(new float[3]
			{
				((Bounds)(ref val)).extents.x,
				((Bounds)(ref val)).extents.y,
				((Bounds)(ref val)).extents.z
			}) : 2f);
			float top = (found ? ((Bounds)(ref val)).max.y : (Position.y + 2f));
			_root = new GameObject("OreFinder highlight");
			_root.transform.position = Position;
			try
			{
				Build(kind, options, top, extent, target);
			}
			catch
			{
				Remove();
				throw;
			}
		}

		private void Build(TargetKind kind, HighlightOptions options, float top, float extent, GameObject target)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: 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_00fd: Expected O, but got Unknown
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: 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)
			if (options.Light)
			{
				GameObject val = new GameObject("Light");
				val.transform.SetParent(_root.transform, false);
				val.transform.position = new Vector3(Position.x, top + 1.5f, Position.z);
				_light = val.AddComponent<Light>();
				_light.type = (LightType)2;
				_light.color = kind.Color;
				_light.range = Mathf.Clamp(extent * 3f + 5f, 8f, 30f);
				_light.intensity = 5f;
				_light.shadows = (LightShadows)0;
				_light.renderMode = (LightRenderMode)1;
			}
			if (options.Beam)
			{
				Material beamMaterial = BeamMaterial;
				if ((Object)(object)beamMaterial != (Object)null)
				{
					GameObject val2 = new GameObject("Beam");
					val2.transform.SetParent(_root.transform, false);
					_beam = val2.AddComponent<LineRenderer>();
					((Renderer)_beam).sharedMaterial = beamMaterial;
					_beam.useWorldSpace = true;
					_beam.positionCount = 2;
					_beam.SetPosition(0, Position);
					_beam.SetPosition(1, Position + Vector3.up * 30f);
					_beam.startWidth = 0.7f;
					_beam.endWidth = 0.15f;
					_beam.alignment = (LineAlignment)0;
					_beam.textureMode = (LineTextureMode)0;
					((Renderer)_beam).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)_beam).receiveShadows = false;
					((Renderer)_beam).lightProbeUsage = (LightProbeUsage)0;
					((Renderer)_beam).reflectionProbeUsage = (ReflectionProbeUsage)0;
				}
			}
			if (options.Glow)
			{
				ApplyGlow(target, kind.Color);
			}
			Update();
		}

		public void Update()
		{
			//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_0072: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			float alpha = Alpha;
			if ((Object)(object)_light != (Object)null)
			{
				_light.intensity = 5f * (0.75f + 0.25f * Mathf.Sin(Time.time * 6f)) * alpha;
			}
			if ((Object)(object)_beam != (Object)null)
			{
				Color color = Kind.Color;
				color.a = 0.85f * alpha;
				Color color2 = Kind.Color;
				color2.a = 0f;
				_beam.startColor = color;
				_beam.endColor = color2;
			}
		}

		public void Remove()
		{
			foreach (Renderer item in _glowing)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.SetPropertyBlock((MaterialPropertyBlock)null);
				}
			}
			_glowing.Clear();
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
				_root = null;
			}
			_light = null;
			_beam = null;
		}

		private static void ConfigureTransparent(Material material)
		{
			if (material.HasProperty("_SrcBlend") && material.HasProperty("_DstBlend"))
			{
				material.SetInt("_SrcBlend", 5);
				material.SetInt("_DstBlend", 10);
			}
			if (material.HasProperty("_ZWrite"))
			{
				material.SetInt("_ZWrite", 0);
			}
			if (material.HasProperty("_Cull"))
			{
				material.SetInt("_Cull", 0);
			}
			material.renderQueue = 3000;
		}

		private void ApplyGlow(GameObject target, Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			MaterialPropertyBlock val = new MaterialPropertyBlock();
			Color val2 = color * 0.6f;
			Renderer[] componentsInChildren = target.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren)
			{
				if (val3 is MeshRenderer || val3 is SkinnedMeshRenderer)
				{
					Material sharedMaterial = val3.sharedMaterial;
					if (!((Object)(object)sharedMaterial == (Object)null) && sharedMaterial.HasProperty(EmissionColorId))
					{
						val3.GetPropertyBlock(val);
						val.SetColor(EmissionColorId, val2);
						val3.SetPropertyBlock(val);
						_glowing.Add(val3);
					}
				}
			}
		}

		private static Bounds BoundsOf(GameObject target, out bool found)
		{
			//IL_0002: 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)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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)
			Bounds result = default(Bounds);
			found = false;
			Renderer[] componentsInChildren = target.GetComponentsInChildren<Renderer>(false);
			foreach (Renderer val in componentsInChildren)
			{
				if (val.enabled && (val is MeshRenderer || val is SkinnedMeshRenderer))
				{
					if (!found)
					{
						result = val.bounds;
						found = true;
					}
					else
					{
						((Bounds)(ref result)).Encapsulate(val.bounds);
					}
				}
			}
			return result;
		}
	}
}
namespace OreFinder.Detection
{
	public static class LocationEntrances
	{
		private static readonly List<Teleport> Buffer = new List<Teleport>();

		public static bool IsSpawned(LocationProxy proxy)
		{
			return (Object)(object)proxy.m_instance != (Object)null;
		}

		public static void Collect(LocationProxy proxy, List<Teleport> results)
		{
			((Component)proxy).GetComponentsInChildren<Teleport>(false, Buffer);
			foreach (Teleport item in Buffer)
			{
				if (TargetCatalog.IsEntrance(item))
				{
					results.Add(item);
				}
			}
			Buffer.Clear();
		}

		public static string LocationName(ZNetView proxyView)
		{
			int num = proxyView.GetZDO().GetInt(ZDOVars.s_location, 0);
			ZoneSystem instance = ZoneSystem.instance;
			ZoneLocation val = (((Object)(object)instance != (Object)null) ? instance.GetLocation(num) : null);
			if (val == null || string.IsNullOrEmpty(val.m_prefabName))
			{
				return num.ToString();
			}
			return val.m_prefabName;
		}
	}
	public sealed class NameList
	{
		private static readonly char[] Separators = new char[6] { ',', ';', '\n', '\r', '\t', ' ' };

		private readonly HashSet<string> _names;

		public bool IsEmpty => _names.Count == 0;

		public int Count => _names.Count;

		private NameList(HashSet<string> names)
		{
			_names = names;
		}

		public static NameList Parse(string? list)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			if (!string.IsNullOrWhiteSpace(list))
			{
				string[] array = list.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
				for (int i = 0; i < array.Length; i++)
				{
					string text = OreFilter.Normalize(array[i]);
					if (text.Length > 0)
					{
						hashSet.Add(text);
					}
				}
			}
			return new NameList(hashSet);
		}

		public bool Contains(string name)
		{
			if (name.Length > 0)
			{
				return _names.Contains(OreFilter.Normalize(name));
			}
			return false;
		}

		public string Describe()
		{
			if (_names.Count != 0)
			{
				return string.Join(", ", _names);
			}
			return "none";
		}
	}
	public sealed class OreFilter
	{
		private const string ItemKeyPrefix = "$item_";

		private static readonly char[] Separators = new char[6] { ',', ';', '\n', '\r', '\t', ' ' };

		private static readonly string[] OreWords = new string[2] { "ore", "scrap" };

		private readonly HashSet<string> _names;

		public bool IsAllOres => _names.Count == 0;

		private OreFilter(HashSet<string> names)
		{
			_names = names;
		}

		public static OreFilter Parse(string? list)
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			if (!string.IsNullOrWhiteSpace(list))
			{
				string[] array = list.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
				for (int i = 0; i < array.Length; i++)
				{
					string text = Normalize(array[i]);
					if (text.Length > 0)
					{
						hashSet.Add(text);
					}
				}
			}
			return new OreFilter(hashSet);
		}

		public static bool IsOreItemName(string name)
		{
			foreach (string item in Words(name))
			{
				string[] oreWords = OreWords;
				foreach (string b in oreWords)
				{
					if (string.Equals(item, b, StringComparison.OrdinalIgnoreCase))
					{
						return true;
					}
				}
			}
			return false;
		}

		public bool TryMatch(string objectPrefabName, IReadOnlyList<string> dropItemNames, out string oreItem)
		{
			if (_names.Count == 0)
			{
				return TryFirstOreDrop(dropItemNames, out oreItem);
			}
			for (int i = 0; i < dropItemNames.Count; i++)
			{
				if (_names.Contains(Normalize(dropItemNames[i])))
				{
					oreItem = dropItemNames[i];
					return true;
				}
			}
			if (_names.Contains(Normalize(objectPrefabName)))
			{
				if (TryFirstOreDrop(dropItemNames, out oreItem))
				{
					return true;
				}
				oreItem = ((dropItemNames.Count > 0) ? dropItemNames[0] : objectPrefabName);
				return true;
			}
			oreItem = string.Empty;
			return false;
		}

		public string Describe()
		{
			if (!IsAllOres)
			{
				return string.Join(", ", _names);
			}
			return "all ores";
		}

		public static string Normalize(string name)
		{
			string text = name.Trim().ToLowerInvariant();
			if (text.StartsWith("$item_", StringComparison.Ordinal))
			{
				text = text.Substring("$item_".Length);
			}
			return text;
		}

		private static bool TryFirstOreDrop(IReadOnlyList<string> dropItemNames, out string oreItem)
		{
			for (int i = 0; i < dropItemNames.Count; i++)
			{
				if (IsOreItemName(dropItemNames[i]))
				{
					oreItem = dropItemNames[i];
					return true;
				}
			}
			oreItem = string.Empty;
			return false;
		}

		private static IEnumerable<string> Words(string name)
		{
			StringBuilder word = new StringBuilder();
			char c = '\0';
			foreach (char c2 in name)
			{
				if ((!char.IsLetterOrDigit(c2) || (char.IsUpper(c2) && char.IsLower(c))) && word.Length > 0)
				{
					yield return word.ToString();
					word.Clear();
				}
				if (char.IsLetterOrDigit(c2))
				{
					word.Append(c2);
				}
				c = c2;
			}
			if (word.Length > 0)
			{
				yield return word.ToString();
			}
		}
	}
	public sealed class OreNames
	{
		private static readonly char[] EntrySeparators = new char[4] { ',', ';', '\n', '\r' };

		private static readonly char[] PairSeparators = new char[2] { '=', ':' };

		private readonly Dictionary<string, string> _names;

		public bool IsEmpty => _names.Count == 0;

		public int Count => _names.Count;

		private OreNames(Dictionary<string, string> names)
		{
			_names = names;
		}

		public static OreNames Parse(string? list)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			if (!string.IsNullOrWhiteSpace(list))
			{
				string[] array = list.Split(EntrySeparators, StringSplitOptions.RemoveEmptyEntries);
				foreach (string text in array)
				{
					int num = text.IndexOfAny(PairSeparators);
					if (num >= 0)
					{
						string text2 = OreFilter.Normalize(text.Substring(0, num));
						string text3 = text.Substring(num + 1).Trim();
						if (text2.Length > 0 && text3.Length > 0)
						{
							dictionary[text2] = text3;
						}
					}
				}
			}
			return new OreNames(dictionary);
		}

		public bool TryGet(string key, string objectPrefabName, out string name)
		{
			if (_names.TryGetValue(OreFilter.Normalize(key), out name))
			{
				return true;
			}
			if (_names.TryGetValue(OreFilter.Normalize(objectPrefabName), out name))
			{
				return true;
			}
			name = string.Empty;
			return false;
		}

		public static string Initials(string displayName)
		{
			List<string> list = new List<string>();
			StringBuilder stringBuilder = new StringBuilder();
			foreach (char c in displayName)
			{
				if (char.IsLetterOrDigit(c))
				{
					stringBuilder.Append(c);
				}
				else if (c != '\'' && c != '’' && stringBuilder.Length > 0)
				{
					list.Add(stringBuilder.ToString());
					stringBuilder.Clear();
				}
			}
			if (stringBuilder.Length > 0)
			{
				list.Add(stringBuilder.ToString());
			}
			if (list.Count == 0)
			{
				return string.Empty;
			}
			if (list.Count == 1)
			{
				string text = list[0];
				if (text.Length != 1)
				{
					return char.ToUpperInvariant(text[0]) + text.Substring(1, 1).ToLowerInvariant();
				}
				return text.ToUpperInvariant();
			}
			return string.Concat(char.ToUpperInvariant(list[0][0]), char.ToUpperInvariant(list[1][0]));
		}

		public string Describe()
		{
			if (_names.Count == 0)
			{
				return "none";
			}
			List<string> list = new List<string>(_names.Count);
			foreach (KeyValuePair<string, string> name in _names)
			{
				list.Add(name.Key + "=" + name.Value);
			}
			return string.Join(", ", list);
		}
	}
	public static class OreScanner
	{
		public static void CollectNearby(Vector3 center, float radius, int locationPrefab, float locationRadius, List<ZNetView> results)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			float num = radius * radius;
			float num2 = locationRadius * locationRadius;
			foreach (KeyValuePair<ZDO, ZNetView> instance2 in instance.m_instances)
			{
				Vector3 val = instance2.Key.GetPosition() - center;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (!(sqrMagnitude > num) || (!(sqrMagnitude > num2) && instance2.Key.GetPrefab() == locationPrefab))
				{
					ZNetView value = instance2.Value;
					if ((Object)(object)value != (Object)null && value.IsValid())
					{
						results.Add(value);
					}
				}
			}
		}
	}
	public sealed class TargetCatalog
	{
		private readonly Dictionary<int, TargetKind?> _byPrefab = new Dictionary<int, TargetKind>();

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

		private readonly List<KeyValuePair<string, string>> _drops = new List<KeyValuePair<string, string>>();

		private bool _hidden;

		public OreFilter Ores { get; }

		public TargetOptions Targets { get; }

		public OreNames? Names { get; }

		public TargetCatalog(OreFilter ores, TargetOptions targets, OreNames? names)
		{
			Ores = ores;
			Targets = targets;
			Names = names;
		}

		public TargetKind? Classify(ZNetView view)
		{
			int prefab = view.GetZDO().GetPrefab();
			if (_byPrefab.TryGetValue(prefab, out TargetKind value))
			{
				return value;
			}
			TargetKind targetKind = Inspect(((Component)view).gameObject);
			_byPrefab[prefab] = targetKind;
			return targetKind;
		}

		private TargetKind? Inspect(GameObject go)
		{
			string prefabName = Utils.GetPrefabName(go);
			return InspectOre(go, prefabName) ?? InspectDungeon(go, prefabName) ?? InspectRoot(go, prefabName) ?? InspectSpawner(go, prefabName) ?? InspectPickable(go, prefabName) ?? InspectTree(go, prefabName);
		}

		public TargetKind? ClassifyEntrance(Teleport teleport, string locationName)
		{
			if (!Targets.Dungeons || !IsEntrance(teleport))
			{
				return null;
			}
			string text = ((!string.IsNullOrEmpty(teleport.m_enterText)) ? teleport.m_enterText : locationName);
			return Make(TargetGroup.Dungeon, text, locationName, Localize(text), hidden: false);
		}

		public static bool IsEntrance(Teleport? teleport)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)teleport != (Object)null && (Object)(object)teleport.m_targetPoint != (Object)null)
			{
				return !Character.InInterior(((Component)teleport).transform.position);
			}
			return false;
		}

		private TargetKind? InspectOre(GameObject go, string prefabName)
		{
			if (!Targets.Ores)
			{
				return null;
			}
			_drops.Clear();
			_dropNames.Clear();
			_hidden = false;
			string text = Collect(go, 0);
			if (_dropNames.Count == 0 || !Ores.TryMatch(prefabName, _dropNames, out string oreItem))
			{
				return null;
			}
			string displayName = ((text.Length > 0) ? Localize(text) : ItemNameFor(oreItem));
			return Make(TargetGroup.Ore, oreItem, prefabName, displayName, _hidden);
		}

		private TargetKind? InspectDungeon(GameObject go, string prefabName)
		{
			if (!Targets.Dungeons)
			{
				return null;
			}
			Teleport componentInChildren = go.GetComponentInChildren<Teleport>(false);
			return ClassifyEntrance(componentInChildren, prefabName);
		}

		private TargetKind? InspectSpawner(GameObject go, string prefabName)
		{
			if (!Targets.Spawners)
			{
				return null;
			}
			SpawnArea componentInChildren = go.GetComponentInChildren<SpawnArea>(false);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				GameObject creature = null;
				foreach (SpawnData prefab in componentInChildren.m_prefabs)
				{
					if ((Object)(object)prefab.m_prefab != (Object)null)
					{
						creature = prefab.m_prefab;
						break;
					}
				}
				return Make(TargetGroup.Spawner, prefabName, prefabName, SpawnerName(go, creature, prefabName), hidden: false);
			}
			CreatureSpawner componentInChildren2 = go.GetComponentInChildren<CreatureSpawner>(false);
			if ((Object)(object)componentInChildren2 == (Object)null || componentInChildren2.m_respawnTimeMinuts <= 0f)
			{
				return null;
			}
			return Make(TargetGroup.Spawner, prefabName, prefabName, SpawnerName(go, componentInChildren2.m_creaturePrefab, prefabName), hidden: false);
		}

		private static string SpawnerName(GameObject go, GameObject? creature, string prefabName)
		{
			HoverText component = go.GetComponent<HoverText>();
			if ((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.m_text))
			{
				return Localize(component.m_text);
			}
			Character val = (((Object)(object)creature != (Object)null) ? creature.GetComponent<Character>() : null);
			if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(val.m_name))
			{
				return Localize(val.m_name) + " spawner";
			}
			return prefabName;
		}

		private TargetKind? InspectRoot(GameObject go, string prefabName)
		{
			if (!Targets.Roots)
			{
				return null;
			}
			ResourceRoot component = go.GetComponent<ResourceRoot>();
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			return Make(TargetGroup.Root, component.m_name, prefabName, Localize(component.m_name), hidden: false);
		}

		private TargetKind? InspectPickable(GameObject go, string prefabName)
		{
			if (Targets.Pickables.IsEmpty)
			{
				return null;
			}
			Pickable component = go.GetComponent<Pickable>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.m_itemPrefab == (Object)null)
			{
				return null;
			}
			string name = ((Object)component.m_itemPrefab).name;
			ItemDrop component2 = component.m_itemPrefab.GetComponent<ItemDrop>();
			string name2 = (((Object)(object)component2 != (Object)null && component2.m_itemData?.m_shared?.m_name != null) ? component2.m_itemData.m_shared.m_name : string.Empty);
			if (!Targets.Pickables.Contains(name) && !Targets.Pickables.Contains(name2) && !Targets.Pickables.Contains(prefabName))
			{
				return null;
			}
			return Make(TargetGroup.Pickable, name, prefabName, Localize(component.GetHoverName()), hidden: false);
		}

		private TargetKind? InspectTree(GameObject go, string prefabName)
		{
			if (Targets.Trees.IsEmpty)
			{
				return null;
			}
			TreeBase component = go.GetComponent<TreeBase>();
			if ((Object)(object)component == (Object)null)
			{
				return null;
			}
			_drops.Clear();
			_dropNames.Clear();
			AddDrops(component.m_dropWhenDestroyed);
			CollectLogs(component.m_logPrefab, 0);
			string text = string.Empty;
			foreach (string dropName in _dropNames)
			{
				if (Targets.Trees.Contains(dropName))
				{
					text = dropName;
					break;
				}
			}
			if (text.Length == 0)
			{
				if (!Targets.Trees.Contains(prefabName))
				{
					return null;
				}
				text = prefabName;
			}
			return Make(TargetGroup.Tree, text, prefabName, ItemNameFor(text), hidden: false);
		}

		private void CollectLogs(GameObject? log, int depth)
		{
			if (!((Object)(object)log == (Object)null) && depth <= 4)
			{
				TreeLog component = log.GetComponent<TreeLog>();
				if (!((Object)(object)component == (Object)null))
				{
					AddDrops(component.m_dropWhenDestroyed);
					CollectLogs(component.m_subLogPrefab, depth + 1);
				}
			}
		}

		private string Collect(GameObject go, int depth)
		{
			string text = string.Empty;
			MineRock5 component = go.GetComponent<MineRock5>();
			if ((Object)(object)component != (Object)null)
			{
				AddDrops(component.m_dropItems);
				text = component.m_name;
			}
			MineRock component2 = go.GetComponent<MineRock>();
			if ((Object)(object)component2 != (Object)null)
			{
				AddDrops(component2.m_dropItems);
				if (text.Length == 0)
				{
					text = component2.m_name;
				}
			}
			DropOnDestroyed component3 = go.GetComponent<DropOnDestroyed>();
			if ((Object)(object)component3 != (Object)null)
			{
				AddDrops(component3.m_dropWhenDestroyed);
			}
			HoverText component4 = go.GetComponent<HoverText>();
			if (text.Length == 0 && (Object)(object)component4 != (Object)null)
			{
				text = component4.m_text;
			}
			if ((Object)(object)go.GetComponent<Beacon>() != (Object)null)
			{
				_hidden = true;
			}
			Destructible component5 = go.GetComponent<Destructible>();
			if ((Object)(object)component5 != (Object)null && (Object)(object)component5.m_spawnWhenDestroyed != (Object)null && depth < 2)
			{
				string text2 = Collect(component5.m_spawnWhenDestroyed, depth + 1);
				if (text.Length == 0)
				{
					text = text2;
				}
			}
			return text;
		}

		private void AddDrops(DropTable? table)
		{
			//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_001d: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			if (table == null)
			{
				return;
			}
			foreach (DropData drop in table.m_drops)
			{
				if (!((Object)(object)drop.m_item == (Object)null))
				{
					ItemDrop component = drop.m_item.GetComponent<ItemDrop>();
					string text = (((Object)(object)component != (Object)null && component.m_itemData?.m_shared?.m_name != null) ? component.m_itemData.m_shared.m_name : string.Empty);
					_drops.Add(new KeyValuePair<string, string>(((Object)drop.m_item).name, text));
					_dropNames.Add(((Object)drop.m_item).name);
					if (text.Length > 0)
					{
						_dropNames.Add(text);
					}
				}
			}
		}

		private string ItemNameFor(string itemName)
		{
			foreach (KeyValuePair<string, string> drop in _drops)
			{
				if ((drop.Key == itemName || drop.Value == itemName) && drop.Value.Length > 0)
				{
					return Localize(drop.Value);
				}
			}
			return itemName;
		}

		private TargetKind Make(TargetGroup group, string key, string prefabName, string displayName, bool hidden)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			string displayName2 = displayName;
			if (Names != null)
			{
				displayName2 = (Names.TryGet(key, prefabName, out string name) ? name : OreNames.Initials(displayName));
			}
			return new TargetKind(group, key, displayName2, TargetKind.ColorFor(group, key), hidden);
		}

		private static string Localize(string text)
		{
			Localization instance = Localization.instance;
			string text2 = ((instance != null) ? instance.Localize(text) : text);
			if (!string.IsNullOrEmpty(text2))
			{
				return text2;
			}
			return text;
		}
	}
	public enum TargetGroup
	{
		Ore,
		Dungeon,
		Root,
		Pickable,
		Tree,
		Spawner
	}
	public static class TargetGroups
	{
		public static readonly string[] SwitchWords = new string[4] { "ores", "dungeons", "roots", "spawners" };

		public static bool TryParse(string? word, out TargetGroup group)
		{
			switch ((word ?? string.Empty).Trim().ToLowerInvariant())
			{
			case "ores":
			case "ore":
				group = TargetGroup.Ore;
				return true;
			case "dungeons":
			case "dungeon":
				group = TargetGroup.Dungeon;
				return true;
			case "root":
			case "roots":
				group = TargetGroup.Root;
				return true;
			case "spawners":
			case "spawner":
				group = TargetGroup.Spawner;
				return true;
			default:
				group = TargetGroup.Ore;
				return false;
			}
		}

		public static string Label(TargetGroup group)
		{
			return group switch
			{
				TargetGroup.Ore => "ores", 
				TargetGroup.Dungeon => "dungeon entrances", 
				TargetGroup.Root => "roots", 
				TargetGroup.Spawner => "spawners", 
				TargetGroup.Pickable => "pickables", 
				_ => "trees", 
			};
		}
	}
	public sealed class TargetKind
	{
		public TargetGroup Group { get; }

		public string Key { get; }

		public string DisplayName { get; }

		public Color Color { get; }

		public bool Hidden { get; }

		public TargetKind(TargetGroup group, string key, string displayName, Color color, bool hidden)
		{
			//IL_001c: 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)
			Group = group;
			Key = key;
			DisplayName = displayName;
			Color = color;
			Hidden = hidden;
		}

		public static Color ColorFor(TargetGroup group, string key)
		{
			//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_0081: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			switch (group)
			{
			case TargetGroup.Dungeon:
				return new Color(0.75f, 0.45f, 1f);
			case TargetGroup.Root:
				return new Color(0.4f, 1f, 0.55f);
			case TargetGroup.Pickable:
				return new Color(0.7f, 1f, 0.3f);
			case TargetGroup.Tree:
				return new Color(0.3f, 0.9f, 0.4f);
			case TargetGroup.Spawner:
				return new Color(1f, 0.3f, 0.35f);
			default:
			{
				string text = key.ToLowerInvariant();
				if (text.Contains("flametal"))
				{
					return new Color(1f, 0.3f, 0.1f);
				}
				if (text.Contains("copper"))
				{
					return new Color(1f, 0.55f, 0.2f);
				}
				if (text.Contains("silver"))
				{
					return new Color(0.9f, 0.95f, 1f);
				}
				if (text.Contains("tin"))
				{
					return new Color(0.7f, 0.85f, 1f);
				}
				if (text.Contains("iron"))
				{
					return new Color(0.9f, 0.4f, 0.15f);
				}
				return new Color(1f, 0.85f, 0.3f);
			}
			}
		}
	}
	public sealed class TargetOptions
	{
		public bool Ores { get; set; } = true;

		public bool Dungeons { get; set; } = true;

		public bool Roots { get; set; } = true;

		public bool Spawners { get; set; } = true;

		public NameList Pickables { get; set; } = NameList.Parse(string.Empty);

		public NameList Trees { get; set; } = NameList.Parse(string.Empty);

		public string Describe()
		{
			List<string> list = new List<string>();
			if (Ores)
			{
				list.Add("ores");
			}
			if (Dungeons)
			{
				list.Add("dungeon entrances");
			}
			if (Roots)
			{
				list.Add("roots");
			}
			if (Spawners)
			{
				list.Add("spawners");
			}
			if (!Pickables.IsEmpty)
			{
				list.Add("pickables (" + Pickables.Describe() + ")");
			}
			if (!Trees.IsEmpty)
			{
				list.Add("trees (" + Trees.Describe() + ")");
			}
			if (list.Count != 0)
			{
				return string.Join(", ", list);
			}
			return "none";
		}
	}
	public enum WishboneRule
	{
		InInventory,
		Equipped,
		NotNeeded
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}