Decompiled source of DiscoveryPins v0.3.6

DiscoveryPins.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Configs;
using DiscoveryPins.Extensions;
using DiscoveryPins.Helpers;
using DiscoveryPins.Pins;
using HarmonyLib;
using Jotunn;
using Jotunn.Managers;
using Jotunn.Utils;
using Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("DiscoveryPins")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DiscoveryPins")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("08a6f7d7-cf93-4931-aecd-abf2ce6ed34c")]
[assembly: AssemblyFileVersion("0.3.6")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.6.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 Logging
{
	internal static class Log
	{
		internal enum InfoLevel
		{
			Low,
			Medium,
			High
		}

		private static ManualLogSource logSource;

		internal static ConfigEntry<InfoLevel> Verbosity { get; set; }

		internal static InfoLevel VerbosityLevel => Verbosity.Value;

		internal static bool IsVerbosityLow => Verbosity.Value >= InfoLevel.Low;

		internal static bool IsVerbosityMedium => Verbosity.Value >= InfoLevel.Medium;

		internal static bool IsVerbosityHigh => Verbosity.Value >= InfoLevel.High;

		internal static void Init(ManualLogSource logSource)
		{
			Log.logSource = logSource;
		}

		internal static void LogDebug(object data)
		{
			logSource.LogDebug(data);
		}

		internal static void LogError(object data)
		{
			logSource.LogError(data);
		}

		internal static void LogFatal(object data)
		{
			logSource.LogFatal(data);
		}

		internal static void LogMessage(object data)
		{
			logSource.LogMessage(data);
		}

		internal static void LogWarning(object data)
		{
			logSource.LogWarning(data);
		}

		internal static void LogInfo(object data, InfoLevel level = InfoLevel.Low)
		{
			if (Verbosity == null || VerbosityLevel >= level)
			{
				logSource.LogInfo(data);
			}
		}

		internal static void LogGameObject(GameObject prefab, bool includeChildren = false)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			LogInfo("***** " + ((Object)prefab).name + " *****");
			Component[] components = prefab.GetComponents<Component>();
			for (int i = 0; i < components.Length; i++)
			{
				LogComponent(components[i]);
			}
			if (!includeChildren)
			{
				return;
			}
			LogInfo("***** " + ((Object)prefab).name + " (children) *****");
			foreach (Transform item in prefab.transform)
			{
				Transform val = item;
				if (Object.op_Implicit((Object)(object)val))
				{
					LogInfo(" - " + ((Object)val).name);
					components = ((Component)val).GetComponents<Component>();
					for (int i = 0; i < components.Length; i++)
					{
						LogComponent(components[i]);
					}
				}
			}
		}

		internal static void LogComponent(Component compo)
		{
			if (!Object.op_Implicit((Object)(object)compo))
			{
				return;
			}
			try
			{
				LogInfo("--- " + ((object)compo).GetType().Name + ": " + ((Object)compo).name + " ---");
			}
			catch (Exception ex)
			{
				LogError(ex.ToString());
				LogWarning("Could not get type name for component!");
				return;
			}
			try
			{
				foreach (PropertyInfo declaredProperty in AccessTools.GetDeclaredProperties(((object)compo).GetType()))
				{
					try
					{
						LogInfo($" - {declaredProperty.Name} = {declaredProperty.GetValue(compo)}");
					}
					catch (Exception ex2)
					{
						LogError(ex2.ToString());
						LogWarning("Could not get property: " + declaredProperty.Name + " for component!");
					}
				}
			}
			catch (Exception ex3)
			{
				LogError(ex3.ToString());
				LogWarning("Could not get properties for component!");
			}
			try
			{
				foreach (FieldInfo declaredField in AccessTools.GetDeclaredFields(((object)compo).GetType()))
				{
					try
					{
						LogInfo($" - {declaredField.Name} = {declaredField.GetValue(compo)}");
					}
					catch (Exception ex4)
					{
						LogError(ex4.ToString());
						LogWarning("Could not get field: " + declaredField.Name + " for component!");
					}
				}
			}
			catch (Exception ex5)
			{
				LogError(ex5.ToString());
				LogWarning("Could not get fields for component!");
			}
		}
	}
}
namespace DiscoveryPins
{
	[BepInPlugin("Searica.Valheim.DiscoveryPins", "DiscoveryPins", "0.3.6")]
	[BepInDependency("com.jotunn.jotunn", "2.23.0")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	internal sealed class DiscoveryPins : BaseUnityPlugin
	{
		internal class AutoPinShortcutConfig
		{
			internal ConfigEntry<bool> Enabled;

			internal ConfigEntry<float> Range;

			internal ConfigEntry<KeyboardShortcut> Shortcut;
		}

		internal class DeathPinConfig
		{
			internal ConfigEntry<bool> PinWhenInvIsEmpty;

			internal ConfigEntry<bool> AutoRemoveEnabled;
		}

		internal class AutoPinConfig
		{
			internal ConfigEntry<bool> Enabled;

			internal ConfigEntry<string> Icon;
		}

		public const string PluginName = "DiscoveryPins";

		internal const string Author = "Searica";

		public const string PluginGUID = "Searica.Valheim.DiscoveryPins";

		public const string PluginVersion = "0.3.6";

		internal static DiscoveryPins Instance;

		internal static ConfigFile ConfigFile;

		internal const string GlobalSection = "Global";

		internal ConfigEntry<float> PinSpacing;

		internal const string AutoPinShortcutSection = "Auto Pin Shortcut";

		internal AutoPinShortcutConfig AutoPinShortcutConfigs;

		internal const string DeathPinSection = "Auto Pin: Tombstone";

		internal DeathPinConfig DeathPinConfigs;

		internal readonly Dictionary<AutoPins.AutoPinCategory, AutoPinConfig> AutoPinConfigs = new Dictionary<AutoPins.AutoPinCategory, AutoPinConfig>();

		internal const string ColorSection = "Pin Colors";

		internal ConfigEntry<bool> EnableColors;

		internal readonly Dictionary<PinType, ConfigEntry<string>> PinColorConfigs = new Dictionary<PinType, ConfigEntry<string>>();

		internal static bool ColorConfigsChanged;

		internal static void OnColorConfigChanged(object obj, EventArgs args)
		{
			if (!ColorConfigsChanged)
			{
				ColorConfigsChanged = true;
			}
		}

		public void Awake()
		{
			Instance = this;
			ConfigFile = ((BaseUnityPlugin)this).Config;
			Log.Init(((BaseUnityPlugin)this).Logger);
			((BaseUnityPlugin)this).Config.Init("Searica.Valheim.DiscoveryPins");
			SetUpConfigEntries();
			UpdatePlugin(saveConfig: true, initialUpdate: true);
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.DiscoveryPins");
			Game.isModded = true;
			((BaseUnityPlugin)this).Config.SetupWatcher();
			ConfigFileManager.OnConfigFileReloaded += delegate
			{
				UpdatePlugin(saveConfig: false);
			};
			SynchronizationManager.OnConfigurationWindowClosed += delegate
			{
				UpdatePlugin();
			};
			SynchronizationManager.OnConfigurationSynchronized += delegate
			{
				UpdatePlugin();
			};
		}

		internal void SetUpConfigEntries()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_00d4: 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_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			PinSpacing = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Global", "Pin Spacing", 10f, "The minimum allowable distance between auto-pins. If a new auto-pin would be closer to an existing pin than the value of Pin Spacing, then no pin will be placed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), synced: false, sectionOrder: true, settingOrder: true, null, new ConfigurationManagerAttributes
			{
				ShowRangeAsPercent = false
			});
			AutoPinShortcutConfigs = new AutoPinShortcutConfig
			{
				Enabled = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Auto Pin Shortcut", "Enabled", value: true, "Whether to allow using the auto pin shortcut."),
				Range = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Auto Pin Shortcut", "Range", 20f, "Maximum distance that auto pins can be generated.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 50f)),
				Shortcut = ((BaseUnityPlugin)this).Config.BindConfigInOrder<KeyboardShortcut>("Auto Pin Shortcut", "Shortcut", new KeyboardShortcut((KeyCode)324, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Shortcut to trigger auto pin.", null, synced: false)
			};
			DeathPinConfigs = new DeathPinConfig
			{
				PinWhenInvIsEmpty = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Auto Pin: Tombstone", "Generate with empty inventory", value: true, "Death pin will/won't be generated if your inventory was empty.", null, synced: false),
				AutoRemoveEnabled = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Auto Pin: Tombstone", "Remove on retrieval", value: true, "Death pin be removed automatically when tombstone is retrieved.", null, synced: false)
			};
			foreach (KeyValuePair<AutoPins.AutoPinCategory, PinType> defaultPinType in AutoPins.DefaultPinTypes)
			{
				string section = $"Auto Pin: {defaultPinType.Key}";
				AutoPinConfigs.Add(defaultPinType.Key, new AutoPinConfig
				{
					Enabled = ((BaseUnityPlugin)this).Config.BindConfigInOrder(section, "Enabled", value: true, "Whether auto pinning is enabled.", null, synced: false),
					Icon = ((BaseUnityPlugin)this).Config.BindConfigInOrder(section, "Icon", PinNames.PinTypeToName(defaultPinType.Value), "Which icon to create the pin with.", (AcceptableValueBase)(object)PlaceablePins.AllowedPlaceablePinNames, synced: false)
				});
			}
			EnableColors = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Pin Colors", "Enabled", value: true, "Whether to enable custom pin colors.", null, synced: false);
			foreach (KeyValuePair<PinType, string> defaultPinColor in PinColors.DefaultPinColors)
			{
				PinColorConfigs.Add(defaultPinColor.Key, ((BaseUnityPlugin)this).Config.BindConfigInOrder("Pin Colors", PinNames.PinTypeToName(defaultPinColor.Key), defaultPinColor.Value, "Color to use for pins of this type.", null, synced: false));
				PinColorConfigs[defaultPinColor.Key].SettingChanged += OnColorConfigChanged;
			}
		}

		private void UpdatePlugin(bool saveConfig = true, bool initialUpdate = false)
		{
			if (ColorConfigsChanged || initialUpdate)
			{
				PinColors.UpdatePinColorMap();
				ColorConfigsChanged = false;
			}
			if (saveConfig)
			{
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		public void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}
	}
}
namespace DiscoveryPins.Pins
{
	internal class AutoPinner : MonoBehaviour
	{
		public const float CloseEnoughXZ = 5f;

		public const float CloseEnoughY = 5f;

		private const float FindPinPrecision = 1f;

		private const float InvokeRepeatingTime = 0.1f;

		public string PinName;

		private bool AutoPinNameChanged;

		public AutoPins.AutoPinCategory AutoPinCategory;

		private Vector3 LastPosition;

		public Vector3 Position
		{
			get
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				if (Object.op_Implicit((Object)(object)((Component)this).transform))
				{
					LastPosition = ((Component)this).transform.position;
				}
				return LastPosition;
			}
		}

		internal static void AddAutoPinner(GameObject target, string pinName, AutoPins.AutoPinCategory pinCategory)
		{
			AutoPinner orAddComponent = ExposedGameObjectExtension.GetOrAddComponent<AutoPinner>(target);
			orAddComponent.PinName = pinName;
			orAddComponent.AutoPinCategory = pinCategory;
		}

		public void Awake()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			LastPosition = ((Component)this).transform.position;
		}

		public void Start()
		{
			((MonoBehaviour)this).InvokeRepeating("CheckForAutoPinShortcut", 0.1f, 0.1f);
		}

		public void UpdatePinName(string pinName, bool markAsChanged = true)
		{
			AutoPinNameChanged = pinName != PinName;
			if (AutoPinNameChanged)
			{
				PinName = pinName;
			}
			AutoPinNameChanged = markAsChanged && AutoPinNameChanged;
		}

		public void CheckForAutoPinShortcut()
		{
			//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_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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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)
			if (!DiscoveryPins.Instance.AutoPinShortcutConfigs.Enabled.Value)
			{
				return;
			}
			KeyboardShortcut value = DiscoveryPins.Instance.AutoPinShortcutConfigs.Shortcut.Value;
			if (!((KeyboardShortcut)(ref value)).IsPressed() || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || !Object.op_Implicit((Object)(object)GameCamera.instance))
			{
				return;
			}
			float dotTolerance = Mathf.Acos((float)Math.PI / 180f * (GameCamera.instance.m_fov / 2f));
			Vector3 position = ((Component)Player.m_localPlayer).transform.position;
			Vector3 lookDir = ((Character)Player.m_localPlayer).m_lookDir;
			if (!TryGetPointsToCheck(out var pointsToCheck))
			{
				return;
			}
			foreach (Vector3 item in pointsToCheck)
			{
				if (IsPointVisibleOrCloseEnough(item, position, lookDir, dotTolerance))
				{
					AddAutoPin();
					break;
				}
			}
		}

		private bool TryGetPointsToCheck(out List<Vector3> pointsToCheck)
		{
			//IL_00be: 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_00a9: 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_007d: 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_00e7: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: 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)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			MeshRenderer val = null;
			Location val2 = null;
			pointsToCheck = null;
			MineRock5 val3 = default(MineRock5);
			if (((Component)this).TryGetComponent<MineRock5>(ref val3) && Object.op_Implicit((Object)(object)val3.m_meshRenderer))
			{
				val = val3.m_meshRenderer;
			}
			else if (Object.op_Implicit((Object)(object)((Component)this).GetComponent<Destructible>()))
			{
				val = ((Component)this).GetComponentInChildren<MeshRenderer>();
			}
			else if (!((Component)this).gameObject.TryGetComponent<Location>(ref val2) && ((Component)this).gameObject.IsLocationProxy())
			{
				val2 = ((Component)this).gameObject.GetComponentInChildren<Location>();
			}
			Bounds bounds = default(Bounds);
			if (Object.op_Implicit((Object)(object)val))
			{
				if (!((Renderer)val).isVisible)
				{
					return false;
				}
				bounds = ((Renderer)val).bounds;
			}
			else
			{
				if (!Object.op_Implicit((Object)(object)val2))
				{
					pointsToCheck = new List<Vector3>(1) { Position };
					return true;
				}
				float num = val2.m_exteriorRadius * 2f;
				((Bounds)(ref bounds))..ctor(((Component)val2).transform.position, new Vector3(num, num, num));
			}
			GetPointSpacing(((Bounds)(ref bounds)).size.x, 5f, out var nPts, out var spacing);
			GetPointSpacing(((Bounds)(ref bounds)).size.y, 5f, out var nPts2, out var spacing2);
			GetPointSpacing(((Bounds)(ref bounds)).size.z, 5f, out var nPts3, out var spacing3);
			pointsToCheck = new List<Vector3>(2)
			{
				Position,
				((Bounds)(ref bounds)).center
			};
			for (int i = 0; i < nPts; i++)
			{
				for (int j = 0; j < nPts2; j++)
				{
					for (int k = 0; k < nPts3; k++)
					{
						pointsToCheck.Add(((Bounds)(ref bounds)).min + new Vector3((float)i * spacing, (float)j * spacing2, (float)k * spacing3));
					}
				}
			}
			return true;
		}

		private static void GetPointSpacing(float size, float targetSpacing, out int nPts, out float spacing)
		{
			nPts = Mathf.CeilToInt(size / targetSpacing);
			spacing = size / (float)nPts;
			nPts++;
		}

		private bool IsPointVisibleOrCloseEnough(Vector3 pos, Vector3 playerPosition, Vector3 lookDir, float dotTolerance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_004f: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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)
			float num = Utils.DistanceXZ(pos, playerPosition);
			if (num > DiscoveryPins.Instance.AutoPinShortcutConfigs.Range.Value)
			{
				return false;
			}
			bool flag = num <= 5f && Mathf.Abs(Position.y - playerPosition.y) <= 5f;
			lookDir = Vector3.Normalize(lookDir);
			float num2 = Vector3.Dot(Vector3.Normalize(pos - ((Component)GameCamera.instance).transform.position), lookDir);
			if ((num2 < 0f || num2 < dotTolerance) && !flag)
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)ZoneSystem.instance))
			{
				float groundHeight = ZoneSystem.instance.GetGroundHeight(pos);
				if (pos.y < groundHeight - 1f)
				{
					return false;
				}
			}
			return true;
		}

		public bool TryGetAutoPinConfig(out DiscoveryPins.AutoPinConfig autoPinConfig)
		{
			if (DiscoveryPins.Instance.AutoPinConfigs.TryGetValue(AutoPinCategory, out autoPinConfig))
			{
				return true;
			}
			return false;
		}

		public bool IsAutoPinEnabled(out DiscoveryPins.AutoPinConfig autoPinConfig)
		{
			if (TryGetAutoPinConfig(out autoPinConfig))
			{
				return autoPinConfig.Enabled.Value;
			}
			return false;
		}

		public bool TryGetAutoPinIcon(out PinType icon)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected I4, but got Unknown
			icon = (PinType)8;
			if (TryGetAutoPinConfig(out var autoPinConfig))
			{
				icon = (PinType)(int)PinNames.PinNameToType(autoPinConfig.Icon.Value);
				return true;
			}
			return false;
		}

		public bool AddAutoPin()
		{
			//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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			if (!IsAutoPinEnabled(out var autoPinConfig))
			{
				return false;
			}
			PinType val = PinNames.PinNameToType(autoPinConfig.Icon.Value);
			if (AutoPinNameChanged)
			{
				PinData val2 = FindExistingPin(Position, val);
				if (val2 != null)
				{
					Log.LogDebug($"Removing old pin with name {val2.m_NamePinData.PinNameText} because auto pin name changed.");
					Minimap.instance.RemovePin(val2);
					AutoPinNameChanged = false;
					AddPin(Position, val, PinName);
					return true;
				}
			}
			if (FindClosestPin(Position, out var closestDis, (PinType)8) != null && closestDis < DiscoveryPins.Instance.PinSpacing.Value)
			{
				return false;
			}
			if (FindExistingPin(Position, val, PinName) != null)
			{
				return false;
			}
			Log.LogDebug($"Adding Auto Pin with name: {PinName}, icon: {autoPinConfig.Icon.Value}, pinType: {val}");
			AddPin(Position, val, PinName);
			return true;
		}

		private static void AddPin(Vector3 pos, PinType type, string name = null)
		{
			//IL_0005: 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)
			Minimap.instance.AddPin(pos, type, name ?? "", true, false, 0L, "");
		}

		public bool RemoveAutoPin()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetAutoPinIcon(out var icon))
			{
				return false;
			}
			return RemovePin(Position, icon, PinName);
		}

		public static bool RemovePin(Vector3 pos, PinType pinType = 8, string name = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PinData val = FindExistingPin(pos, pinType, name);
			if (val != null)
			{
				Minimap.instance.RemovePin(val);
				return true;
			}
			return false;
		}

		public static PinData FindExistingPin(Vector3 pos, PinType type = 8, string name = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			float closestDis;
			PinData val = FindClosestPin(pos, out closestDis, type);
			if (closestDis > 1f)
			{
				return null;
			}
			if (!string.IsNullOrEmpty(name) && val.m_name != name)
			{
				return null;
			}
			return val;
		}

		public static PinData FindClosestPin(Vector3 pos, out float closestDis, PinType type = 8)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			List<(PinData, float)> list = new List<(PinData, float)>();
			foreach (PinData pin in Minimap.instance.m_pins)
			{
				if ((int)type == 8 || pin.m_type == type)
				{
					list.Add((pin, Utils.DistanceXZ(pos, pin.m_pos)));
				}
			}
			PinData val = null;
			closestDis = float.MaxValue;
			foreach (var (val2, num) in list)
			{
				if (val == null || num < closestDis)
				{
					val = val2;
					closestDis = num;
				}
			}
			return val;
		}
	}
	internal static class AutoPins
	{
		internal enum AutoPinCategory
		{
			Dungeon,
			Location,
			Ore,
			Portal
		}

		internal static Dictionary<AutoPinCategory, PinType> DefaultPinTypes = new Dictionary<AutoPinCategory, PinType>
		{
			{
				AutoPinCategory.Dungeon,
				(PinType)6
			},
			{
				AutoPinCategory.Location,
				(PinType)0
			},
			{
				AutoPinCategory.Ore,
				(PinType)2
			},
			{
				AutoPinCategory.Portal,
				(PinType)3
			}
		};
	}
	[HarmonyPatch]
	internal static class PinColors
	{
		internal static Dictionary<PinType, Color> PinColorMap = new Dictionary<PinType, Color>();

		private const string Red = "#d43d3d";

		private const string Cyan = "#35b5cc";

		private const string Orange = "#d6b340";

		private const string LightDusk = "#737373";

		private const string Brown = "#a86840";

		private const string Purple = "#9c39ed";

		private const string White = "#ffffff";

		internal static readonly Dictionary<PinType, string> DefaultPinColors = new Dictionary<PinType, string>
		{
			{
				(PinType)4,
				"#d43d3d"
			},
			{
				(PinType)5,
				"#35b5cc"
			},
			{
				(PinType)0,
				"#d6b340"
			},
			{
				(PinType)1,
				"#35b5cc"
			},
			{
				(PinType)6,
				"#a86840"
			},
			{
				(PinType)2,
				"#737373"
			},
			{
				(PinType)3,
				"#d43d3d"
			},
			{
				(PinType)7,
				"#ffffff"
			},
			{
				(PinType)10,
				"#ffffff"
			},
			{
				(PinType)9,
				"#9c39ed"
			},
			{
				(PinType)11,
				"#ffffff"
			},
			{
				(PinType)12,
				"#ffffff"
			},
			{
				(PinType)13,
				"#ffffff"
			}
		};

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Minimap), "UpdatePins")]
		private static void MinimapUpdatePins_PostFix()
		{
			UpdatePinsColor();
		}

		public static void UpdatePinColorMap()
		{
			//IL_003d: 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 (!DiscoveryPins.Instance.EnableColors.Value)
			{
				return;
			}
			PinColorMap.Clear();
			foreach (KeyValuePair<PinType, ConfigEntry<string>> pinColorConfig in DiscoveryPins.Instance.PinColorConfigs)
			{
				PinColorMap[pinColorConfig.Key] = pinColorConfig.Value.Value.ToColor();
			}
		}

		public static void UpdatePinsColor()
		{
			//IL_0048: 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_0062: 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)
			if (!DiscoveryPins.Instance.EnableColors.Value)
			{
				return;
			}
			foreach (PinData pin in Minimap.instance.m_pins)
			{
				if (!((Object)(object)pin.m_iconElement == (Object)null) && !pin.m_shouldDelete && PinColorMap.TryGetValue(pin.m_type, out var value))
				{
					Image iconElement = pin.m_iconElement;
					((Graphic)iconElement).color = ((Graphic)iconElement).color * value;
				}
			}
		}
	}
	internal class PinNames
	{
		private static readonly Dictionary<PinType, string> PinTypeToNameMap = new Dictionary<PinType, string>
		{
			{
				(PinType)0,
				"Fireplace"
			},
			{
				(PinType)1,
				"House"
			},
			{
				(PinType)2,
				"Hammer"
			},
			{
				(PinType)3,
				"Ball"
			},
			{
				(PinType)6,
				"Cave"
			}
		};

		private static Dictionary<string, PinType> _PinNameToTypeMap;

		private static Dictionary<string, PinType> PinNameToTypeMap
		{
			get
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				if (_PinNameToTypeMap == null)
				{
					_PinNameToTypeMap = new Dictionary<string, PinType>();
					foreach (KeyValuePair<PinType, string> item in PinTypeToNameMap)
					{
						_PinNameToTypeMap.Add(item.Value, item.Key);
					}
				}
				return _PinNameToTypeMap;
			}
		}

		internal static string PinTypeToName(PinType pinType)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (PinTypeToNameMap.TryGetValue(pinType, out var value))
			{
				return value;
			}
			return ((object)(PinType)(ref pinType)).ToString();
		}

		internal static PinType PinNameToType(string pinName)
		{
			//IL_0012: 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 (PinNameToTypeMap.TryGetValue(pinName, out var value))
			{
				return value;
			}
			return EnumUtils.ParseEnum<PinType>(pinName);
		}
	}
	internal static class PlaceablePins
	{
		private static readonly List<PinType> PlaceablePinTypes = new List<PinType>
		{
			(PinType)0,
			(PinType)1,
			(PinType)2,
			(PinType)3,
			(PinType)6
		};

		private static List<string> _PlaceablePinNames;

		private static List<string> PlaceablePinNames => _PlaceablePinNames ?? (_PlaceablePinNames = PlaceablePinTypes.Select((PinType x) => PinNames.PinTypeToName(x)).ToList());

		internal static AcceptableValueList<string> AllowedPlaceablePinNames => new AcceptableValueList<string>(PlaceablePinNames.ToArray());
	}
}
namespace DiscoveryPins.Patches
{
	[HarmonyPatch]
	internal static class DeathPins
	{
		public static bool InvIsEmpty;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "OnDeath")]
		public static void PlayerOnDeath_Prefix(Player __instance)
		{
			InvIsEmpty = ((Humanoid)__instance).m_inventory.NrOfItems() < 1;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "OnDeath")]
		public static void PlayerOnDeath_Postfix(Player __instance)
		{
			//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_004a: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			if (InvIsEmpty && !DiscoveryPins.Instance.DeathPinConfigs.PinWhenInvIsEmpty.Value)
			{
				Vector3 position = ((Component)__instance).transform.position;
				Log.LogDebug("Negating pin at '" + ((Vector3)(ref position)).ToString("F0") + "' because inventory was empty\n");
				AutoPinner.RemovePin(position, (PinType)4);
				PlayerProfile playerProfile = Game.instance.GetPlayerProfile();
				playerProfile.GetWorldData(ZNet.instance.GetWorldUID()).m_haveDeathPoint = false;
				playerProfile.GetWorldData(ZNet.instance.GetWorldUID()).m_deathPoint = Vector3.zero;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TombStone), "GiveBoost")]
		public static void TombStoneGiveBoost_Postfix(TombStone __instance)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (DiscoveryPins.Instance.DeathPinConfigs.AutoRemoveEnabled.Value)
			{
				AutoPinner.RemovePin(((Component)__instance).transform.position, (PinType)4);
			}
		}
	}
	[HarmonyPatch]
	internal static class DungeonPins
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Location), "Awake")]
		private static void Location_AwakePostfix(Location __instance)
		{
			if (__instance.TryGetInteriorEntrance(out var teleport, out var name))
			{
				AutoPinner.AddAutoPinner(((Component)teleport).gameObject, name, AutoPins.AutoPinCategory.Dungeon);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Teleport), "Interact")]
		private static void TeleportInteract_Prefix(Teleport __instance)
		{
			AutoPinner autoPinner = default(AutoPinner);
			if (((Component)__instance).TryGetComponent<AutoPinner>(ref autoPinner))
			{
				autoPinner.AddAutoPin();
			}
		}
	}
	[HarmonyPatch]
	internal static class LocationPins
	{
		private static readonly HashSet<string> LocationNames = new HashSet<string>();

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

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Location), "Awake")]
		private static void Location_AwakePostfix(Location __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance))
			{
				string prefabName = Utils.GetPrefabName(((Component)__instance).gameObject);
				if (!OverworldLocationNamesMap.ContainsKey(prefabName) && __instance.TryGetOverworldDungeon(out var _, out var name))
				{
					OverworldLocationNamesMap[prefabName] = name;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(LocationProxy), "SpawnLocation")]
		private static void AddAutoPinnerToSpawnedLocationProxy(LocationProxy __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)__instance.m_instance))
			{
				string prefabName = Utils.GetPrefabName(__instance.m_instance);
				if (OverworldLocationNamesMap.ContainsKey(prefabName))
				{
					AutoPinner.AddAutoPinner(((Component)__instance).gameObject, OverworldLocationNamesMap[prefabName], AutoPins.AutoPinCategory.Location);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class OrePins
	{
		private static readonly List<string> OreNames = new List<string>(6) { "Tin", "Copper", "Silver", "Obsidian", "Giant", "Tar" };

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

		internal static void TryAddAutoPinnerToOre(GameObject prefab)
		{
			if (IsOrePrefab(prefab, out var OreName) && !OrePrefabNames.Contains(((Object)prefab).name))
			{
				OrePrefabNames.Add(((Object)prefab).name);
				AutoPinner.AddAutoPinner(prefab, OreName, AutoPins.AutoPinCategory.Ore);
			}
		}

		private static bool IsOrePrefab(GameObject gameObject, out string OreName)
		{
			bool flag = false;
			OreName = null;
			foreach (string oreName in OreNames)
			{
				if (StringExtensions.Contains(((Object)gameObject).name, oreName, StringComparison.OrdinalIgnoreCase))
				{
					OreName = oreName;
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)gameObject.GetComponent<Destructible>()))
			{
				HoverText val = default(HoverText);
				if (gameObject.TryGetComponent<HoverText>(ref val))
				{
					OreName = val.m_text;
				}
				return true;
			}
			MineRock5 val2 = default(MineRock5);
			if (gameObject.TryGetComponent<MineRock5>(ref val2))
			{
				OreName = val2.m_name;
				return true;
			}
			if (gameObject.IsTarPit())
			{
				return true;
			}
			return false;
		}

		internal static bool TryGetOreName(GameObject prefab, out string OreName)
		{
			HoverText val = default(HoverText);
			foreach (string oreName in OreNames)
			{
				if (StringExtensions.Contains(((Object)prefab).name, oreName, StringComparison.OrdinalIgnoreCase))
				{
					if (prefab.TryGetComponent<HoverText>(ref val))
					{
						OreName = val.m_text;
						return true;
					}
					OreName = oreName;
					return true;
				}
			}
			OreName = null;
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MineRock5), "RPC_Damage")]
		public static void MineRock5_RPCDamage_Prefix(MineRock5 __instance)
		{
			AutoPinner autoPinner = default(AutoPinner);
			if (((Component)__instance).TryGetComponent<AutoPinner>(ref autoPinner))
			{
				autoPinner.AddAutoPin();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(MineRock5), "AllDestroyed")]
		public static void AllDestroyed(MineRock5 __instance, bool __result)
		{
			AutoPinner autoPinner = default(AutoPinner);
			if (__result && ((Component)__instance).TryGetComponent<AutoPinner>(ref autoPinner))
			{
				autoPinner.RemoveAutoPin();
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Destructible), "RPC_Damage")]
		public static void Destructible_RPCDamage_Prefix(Destructible __instance)
		{
			AutoPinner autoPinner = default(AutoPinner);
			if (((Component)__instance).TryGetComponent<AutoPinner>(ref autoPinner))
			{
				autoPinner.AddAutoPin();
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Destructible), "Destroy")]
		public static void Destructible_Destroy_Prefix(Destructible __instance)
		{
			AutoPinner autoPinner = default(AutoPinner);
			if (((Component)__instance).TryGetComponent<AutoPinner>(ref autoPinner) && (!Object.op_Implicit((Object)(object)__instance.m_spawnWhenDestroyed) || !Object.op_Implicit((Object)(object)__instance.m_spawnWhenDestroyed.GetComponent<MineRock5>()) || !TryGetOreName(__instance.m_spawnWhenDestroyed, out var _)))
			{
				autoPinner.RemoveAutoPin();
			}
		}
	}
	[HarmonyPatch]
	internal static class PlaceRemovePatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Piece), "OnPlaced")]
		public static void Piece_OnPlaced_Postfix(Piece __instance)
		{
			AutoPinner autoPinner = default(AutoPinner);
			if (Object.op_Implicit((Object)(object)__instance) && ((Component)__instance).TryGetComponent<AutoPinner>(ref autoPinner))
			{
				autoPinner.AddAutoPin();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Piece), "DropResources")]
		public static void Piece_DropResources_Postfix(Piece __instance)
		{
			AutoPinner autoPinner = default(AutoPinner);
			if (Object.op_Implicit((Object)(object)__instance) && ((Component)__instance).TryGetComponent<AutoPinner>(ref autoPinner))
			{
				autoPinner.RemoveAutoPin();
			}
		}
	}
	[HarmonyPatch]
	internal static class PortalPins
	{
		private const string DefaultPortalName = "Portal";

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

		internal static void TryAddAutoPinnerToPortal(GameObject prefab)
		{
			if (IsPortal(prefab) && !PortalPrefabNames.Contains(((Object)prefab).name))
			{
				PortalPrefabNames.Add(((Object)prefab).name);
				AutoPinner.AddAutoPinner(prefab, "Portal", AutoPins.AutoPinCategory.Portal);
			}
		}

		internal static bool IsPortal(GameObject prefab)
		{
			return Object.op_Implicit((Object)(object)prefab.GetComponent<TeleportWorld>());
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TeleportWorld), "Awake")]
		internal static void TeleportWorld_Awake_Postfix(TeleportWorld __instance)
		{
			AutoPinner autoPinner = default(AutoPinner);
			if (Object.op_Implicit((Object)(object)__instance) && ((Component)__instance).TryGetComponent<AutoPinner>(ref autoPinner))
			{
				autoPinner.UpdatePinName(GetPortalAutoPinName(__instance), markAsChanged: false);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(TeleportWorld), "RPC_SetTag")]
		internal static void TeleportWorld_RPC_SetTag_Postfix(TeleportWorld __instance)
		{
			AutoPinner autoPinner = default(AutoPinner);
			if (Object.op_Implicit((Object)(object)__instance) && ((Component)__instance).TryGetComponent<AutoPinner>(ref autoPinner))
			{
				autoPinner.UpdatePinName(GetPortalAutoPinName(__instance));
			}
		}

		internal static string GetPortalAutoPinName(TeleportWorld teleportWorld)
		{
			string text = teleportWorld.GetText();
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			return "Portal";
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TeleportWorld), "Teleport")]
		internal static void TeleportWorld_Teleport_Prefix(TeleportWorld __instance)
		{
			TriggerAutoPinPortal(__instance);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TeleportWorld), "GetHoverText")]
		internal static void TeleportWorld_GetHoverText_Prefix(TeleportWorld __instance)
		{
			TriggerAutoPinPortal(__instance);
		}

		private static void TriggerAutoPinPortal(TeleportWorld teleportWorld)
		{
			AutoPinner autoPinner = default(AutoPinner);
			if (Object.op_Implicit((Object)(object)teleportWorld) && ((Component)teleportWorld).TryGetComponent<AutoPinner>(ref autoPinner))
			{
				autoPinner.AddAutoPin();
			}
		}
	}
	[HarmonyPatch]
	internal static class ZoneSystemPatches
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		[HarmonyPatch(typeof(ZoneSystem), "Start")]
		private static void ZoneSystem_Start_Prefix()
		{
			//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)
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).name != "main")
			{
				return;
			}
			foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
			{
				if (prefab.IsTopLevelPrefab())
				{
					OrePins.TryAddAutoPinnerToOre(prefab);
					PortalPins.TryAddAutoPinnerToPortal(prefab);
				}
			}
		}
	}
}
namespace DiscoveryPins.Helpers
{
	internal static class EnumUtils
	{
		internal static IEnumerable<T> GetEnumValues<T>()
		{
			return Enum.GetValues(typeof(T)).Cast<T>();
		}

		public static T ParseEnum<T>(string value)
		{
			return (T)Enum.Parse(typeof(T), value, ignoreCase: true);
		}
	}
	internal static class ReflectionUtils
	{
		public const BindingFlags AllBindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty;

		internal static MethodInfo GetMethod(Type type, string name, Type[] types)
		{
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name == name && HasMatchingParameterTypes(0, types, methodInfo.GetParameters()))
				{
					return methodInfo;
				}
			}
			return null;
		}

		internal static MethodInfo GetGenericMethod(Type type, string name, int genericParameterCount, Type[] types)
		{
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.IsGenericMethod && methodInfo.ContainsGenericParameters && methodInfo.Name == name && HasMatchingParameterTypes(genericParameterCount, types, methodInfo.GetParameters()))
				{
					return methodInfo;
				}
			}
			return null;
		}

		private static bool HasMatchingParameterTypes(int genericParameterCount, Type[] types, ParameterInfo[] parameters)
		{
			if (parameters.Length < genericParameterCount || parameters.Length != types.Length)
			{
				return false;
			}
			int num = 0;
			for (int i = 0; i < parameters.Length; i++)
			{
				if (parameters[i].ParameterType.IsGenericParameter)
				{
					num++;
				}
				else if (types[i] != parameters[i].ParameterType)
				{
					return false;
				}
			}
			if (num != genericParameterCount)
			{
				return false;
			}
			return true;
		}
	}
}
namespace DiscoveryPins.Extensions
{
	internal static class GameObjectExtensions
	{
		private static readonly Dictionary<string, bool> IsPrefabLocationProxyMap = new Dictionary<string, bool>();

		private static readonly Dictionary<string, bool> IsPrefabTarPitMap = new Dictionary<string, bool>();

		internal static bool IsTopLevelPrefab(this GameObject gameObject)
		{
			return !Object.op_Implicit((Object)(object)gameObject.transform.parent);
		}

		internal static bool IsTarPit(this GameObject gameObject)
		{
			string prefabName = Utils.GetPrefabName(gameObject);
			if (!IsPrefabTarPitMap.TryGetValue(prefabName, out var value))
			{
				value = Object.op_Implicit((Object)(object)gameObject.transform.Find("TarLiquid"));
				IsPrefabTarPitMap[prefabName] = value;
			}
			return value;
		}

		internal static bool IsLocationProxy(this GameObject gameObject)
		{
			string prefabName = Utils.GetPrefabName(gameObject);
			if (!IsPrefabLocationProxyMap.TryGetValue(prefabName, out var value))
			{
				value = Object.op_Implicit((Object)(object)gameObject.GetComponent<LocationProxy>());
				IsPrefabTarPitMap[prefabName] = value;
			}
			return value;
		}
	}
	internal static class LocationExtensions
	{
		private const string EntranceName = "GateWay";

		private const string ExteriorName = "exterior";

		internal static bool TryGetInteriorEntrance(this Location location, out Teleport teleport, out string name)
		{
			teleport = null;
			name = string.Empty;
			if (!location.m_hasInterior)
			{
				return false;
			}
			if (TryGetTeleportEntrance(((Component)location).transform, out teleport, out name))
			{
				return true;
			}
			Transform val = ((Component)location).transform.Find("exterior");
			if (Object.op_Implicit((Object)(object)val) && TryGetTeleportEntrance(val, out teleport, out name))
			{
				return true;
			}
			return false;
		}

		internal static bool TryGetTeleportEntrance(Transform parent, out Teleport entrance, out string name)
		{
			name = string.Empty;
			entrance = null;
			for (int i = 0; i < ((Component)parent).transform.childCount; i++)
			{
				if (((Component)((Component)parent).transform.GetChild(i)).TryGetComponent<Teleport>(ref entrance) && entrance != null)
				{
					if (!Utility.IsNullOrWhiteSpace(entrance.m_enterText))
					{
						name = entrance.m_enterText;
					}
					return true;
				}
			}
			return false;
		}

		internal static bool TryGetOverworldDungeon(this Location location, out DungeonGenerator generator, out string name)
		{
			generator = null;
			name = string.Empty;
			if (location.m_hasInterior)
			{
				return false;
			}
			if (!location.TryGetDungeonGenerator(out generator) || !Object.op_Implicit((Object)(object)generator))
			{
				return false;
			}
			name = ((object)(Theme)(ref generator.m_themes)).ToString().Replace("Goblin", "Fuling");
			return true;
		}

		internal static bool TryGetDungeonGenerator(this Location location, out DungeonGenerator generator)
		{
			generator = null;
			if (Object.op_Implicit((Object)(object)location.m_generator))
			{
				generator = location.m_generator;
				return true;
			}
			for (int i = 0; i < ((Component)location).transform.childCount; i++)
			{
				if (((Component)((Component)location).transform.GetChild(i)).TryGetComponent<DungeonGenerator>(ref generator) && generator != null)
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class SafeInvokEvents
	{
		public static void SafeInvoke(this Action events)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action action = (Action)invocationList[i];
				try
				{
					action();
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TArg1>(this Action<TArg1> events, TArg1 arg1)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TArg1> action = (Action<TArg1>)invocationList[i];
				try
				{
					action(arg1);
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TArg1, TArg2>(this Action<TArg1, TArg2> events, TArg1 arg1, TArg2 arg2)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TArg1, TArg2> action = (Action<TArg1, TArg2>)invocationList[i];
				try
				{
					action(arg1, arg2);
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TEventArg>(this EventHandler<TEventArg> events, object sender, TEventArg arg1)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				EventHandler<TEventArg> eventHandler = (EventHandler<TEventArg>)invocationList[i];
				try
				{
					eventHandler(sender, arg1);
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {eventHandler.Method.DeclaringType.Name}.{eventHandler.Method.Name}:\n{ex}");
				}
			}
		}
	}
	internal static class StringExtensions
	{
		private static StringBuilder sb = new StringBuilder(9);

		public static Color ToColor(this string color)
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			sb.Append(color);
			if (color.StartsWith("#", StringComparison.InvariantCulture))
			{
				sb.Remove(0, 1);
			}
			if (sb.Length == 6)
			{
				sb.Append("FF");
			}
			uint num = Convert.ToUInt32(sb.ToString(), 16);
			sb.Clear();
			return new Color((float)((num & 0xFF000000u) >> 24) / 255f, (float)((num & 0xFF0000) >> 16) / 255f, (float)((num & 0xFF00) >> 8) / 255f, (float)(num & 0xFFu) / 255f);
		}

		public static bool Contains(this string orig, string value, StringComparison comparisonType)
		{
			return orig.IndexOf(value, comparisonType) > -1;
		}
	}
}
namespace Configs
{
	public static class ConfigFileManager
	{
		internal static string ConfigFileName;

		internal static string ConfigFileFullPath;

		internal static DateTime lastRead = DateTime.MinValue;

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

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

		private static readonly List<string> ConfigManagerGUIDs = new List<string> { "_shudnal.ConfigurationManager", "com.bepis.bepinex.configurationmanager" };

		private static BaseUnityPlugin _configManager = null;

		private const string WindowChangedEventName = "DisplayingWindowChanged";

		private const string DisplayingWindowName = "DisplayingWindow";

		private static PropertyInfo _dispWindowInfo = null;

		private static BaseUnityPlugin ConfigManager
		{
			get
			{
				if ((Object)(object)_configManager == (Object)null)
				{
					foreach (string configManagerGUID in ConfigManagerGUIDs)
					{
						if (Chainloader.PluginInfos.TryGetValue(configManagerGUID, out var value) && Object.op_Implicit((Object)(object)value.Instance))
						{
							_configManager = value.Instance;
							break;
						}
					}
				}
				return _configManager;
			}
		}

		private static PropertyInfo DisplayWindowInfo
		{
			get
			{
				if ((object)_dispWindowInfo == null)
				{
					_dispWindowInfo = ((object)ConfigManager).GetType().GetProperty("DisplayingWindow");
				}
				return _dispWindowInfo;
			}
		}

		internal static event Action OnConfigFileReloaded;

		internal static event Action OnConfigWindowClosed;

		private static string GetOrderedSectionName(string section)
		{
			if (!_sectionToSectionNumber.TryGetValue(section, out var value))
			{
				value = _sectionToSectionNumber.Count + 1;
				_sectionToSectionNumber[section] = value;
			}
			return $"{value} - {section}";
		}

		private static int GetSettingOrder(string section)
		{
			if (!_sectionToSettingOrder.TryGetValue(section, out var value))
			{
				value = 0;
			}
			_sectionToSettingOrder[section] = value - 1;
			return value;
		}

		private static void InvokeOnConfigFileReloaded()
		{
			Action onConfigFileReloaded = ConfigFileManager.OnConfigFileReloaded;
			if (onConfigFileReloaded != null)
			{
				onConfigFileReloaded.SafeInvoke();
			}
		}

		private static void InvokeOnConfigWindowClosed()
		{
			Action onConfigWindowClosed = ConfigFileManager.OnConfigWindowClosed;
			if (onConfigWindowClosed != null)
			{
				onConfigWindowClosed.SafeInvoke();
			}
		}

		public static void Init(this ConfigFile configFile, string GUID, bool saveOnConfigSet = false)
		{
			configFile.SaveOnConfigSet = saveOnConfigSet;
			ConfigFileName = GUID + ".cfg";
			ConfigFileFullPath = Path.Combine(Paths.ConfigPath, ConfigFileName);
		}

		public static bool DisableSaveOnConfigSet(this ConfigFile configFile)
		{
			bool saveOnConfigSet = configFile.SaveOnConfigSet;
			configFile.SaveOnConfigSet = false;
			return saveOnConfigSet;
		}

		public static ConfigEntry<T> BindConfigInOrder<T>(this ConfigFile configFile, string section, string name, T value, string description, AcceptableValueBase acceptVals = null, bool synced = true, bool sectionOrder = true, bool settingOrder = true, Action<ConfigEntryBase> drawer = null, ConfigurationManagerAttributes configAttributes = null)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			section = (sectionOrder ? GetOrderedSectionName(section) : section);
			int value2 = (settingOrder ? GetSettingOrder(section) : 0);
			if (configAttributes == null)
			{
				configAttributes = new ConfigurationManagerAttributes();
			}
			configAttributes.Order = value2;
			return configFile.BindConfig(section, name, value, description, acceptVals, synced, drawer, configAttributes);
		}

		public static ConfigEntry<T> BindConfig<T>(this ConfigFile configFile, string section, string name, T value, string description, AcceptableValueBase acceptVals = null, bool synced = true, Action<ConfigEntryBase> drawer = null, ConfigurationManagerAttributes configAttributes = null)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			string extendedDescription = GetExtendedDescription(description, synced);
			if (configAttributes == null)
			{
				configAttributes = new ConfigurationManagerAttributes();
			}
			configAttributes.IsAdminOnly = synced;
			if (drawer != null)
			{
				configAttributes.CustomDrawer = drawer;
			}
			return configFile.Bind<T>(section, name, value, new ConfigDescription(extendedDescription, acceptVals, new object[1] { configAttributes }));
		}

		internal static string GetExtendedDescription(string description, bool synchronizedSetting)
		{
			return description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]");
		}

		internal static void SetupWatcher(this ConfigFile configFile)
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
			fileSystemWatcher.Changed += configFile.ReloadConfigFile;
			fileSystemWatcher.Created += configFile.ReloadConfigFile;
			fileSystemWatcher.Renamed += configFile.ReloadConfigFile;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		internal static void ReloadConfigFile(this ConfigFile configFile, object sender, FileSystemEventArgs eventArgs)
		{
			if (!File.Exists(ConfigFileFullPath))
			{
				return;
			}
			try
			{
				DateTime lastWriteTime = File.GetLastWriteTime(eventArgs.FullPath);
				if (lastRead != lastWriteTime)
				{
					Log.LogInfo("Reloading config file");
					bool saveOnConfigSet = configFile.DisableSaveOnConfigSet();
					configFile.Reload();
					configFile.SaveOnConfigSet = saveOnConfigSet;
					InvokeOnConfigFileReloaded();
					lastRead = lastWriteTime;
				}
			}
			catch
			{
				Log.LogError("There was an issue loading your " + ConfigFileName);
				Log.LogError("Please check your config entries for spelling and format!");
			}
		}

		internal static void CheckForConfigManager(this ConfigFile config)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)SystemInfo.graphicsDeviceType != 4 && !((Object)(object)ConfigManager == (Object)null))
			{
				Log.LogDebug("Configuration manager found, hooking DisplayingWindowChanged");
				EventInfo @event = ((object)ConfigManager).GetType().GetEvent("DisplayingWindowChanged");
				if (!(@event == null))
				{
					Action<object, object> action = OnConfigManagerDisplayingWindowChanged;
					Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, action.Target, action.Method);
					@event.AddEventHandler(ConfigManager, handler);
				}
			}
		}

		private static void OnConfigManagerDisplayingWindowChanged(object sender, object e)
		{
			if (!(DisplayWindowInfo == null) && !(bool)DisplayWindowInfo.GetValue(ConfigManager, null))
			{
				InvokeOnConfigWindowClosed();
			}
		}

		private static void SafeInvoke(this Action events)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action action = (Action)invocationList[i];
				try
				{
					action();
				}
				catch (Exception arg)
				{
					Log.LogWarning("Exception thrown at event " + new StackFrame(1).GetMethod().Name + $" in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{arg}");
				}
			}
		}
	}
}