Decompiled source of DiscoveryPins v0.1.1

DiscoveryPins.dll

Decompiled 4 hours 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.Configuration;
using BepInEx.Logging;
using DiscoveryPins.Extensions;
using DiscoveryPins.Helpers;
using DiscoveryPins.Pins;
using HarmonyLib;
using Jotunn;
using Jotunn.Managers;
using Jotunn.Utils;
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.1.1")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.1.0")]
[module: UnverifiableCode]
namespace DiscoveryPins
{
	[BepInPlugin("Searica.Valheim.DiscoveryPins", "DiscoveryPins", "0.1.1")]
	[BepInDependency("com.jotunn.jotunn", "2.22.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.1.1";

		internal static DiscoveryPins Instance;

		internal static ConfigFile ConfigFile;

		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();
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.DiscoveryPins");
			Game.isModded = true;
			UpdatePlugin(saveConfig: true, initialUpdate: true);
			((BaseUnityPlugin)this).Config.SetupWatcher();
			ConfigFileExtensions.OnConfigFileReloaded += delegate
			{
				UpdatePlugin(saveConfig: false);
			};
			SynchronizationManager.OnConfigurationWindowClosed += delegate
			{
				UpdatePlugin();
			};
			SynchronizationManager.OnConfigurationSynchronized += delegate
			{
				UpdatePlugin();
			};
		}

		internal void SetUpConfigEntries()
		{
			//IL_008d: 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_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			int num = 1;
			AutoPinShortcutConfigs = new AutoPinShortcutConfig
			{
				Enabled = ((BaseUnityPlugin)this).Config.BindConfig("Auto Pin Shortcut", "Enabled", value: true, "Whether to allow using the auto pin shortcut.", null, synced: true, 0, num),
				Range = ((BaseUnityPlugin)this).Config.BindConfig("Auto Pin Shortcut", "Range", 50f, "Maximum distance that auto pins can be generated.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), synced: true, 0, num),
				Shortcut = ((BaseUnityPlugin)this).Config.BindConfig<KeyboardShortcut>("Auto Pin Shortcut", "Shortcut", new KeyboardShortcut((KeyCode)308, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Shortcut to trigger auto pin.", null, synced: false, 0, num)
			};
			num++;
			DeathPinConfigs = new DeathPinConfig
			{
				PinWhenInvIsEmpty = ((BaseUnityPlugin)this).Config.BindConfig("Auto Pin: Tombstone", "Generate with empty inventory", value: true, "Death pin will/won't be generated if your inventory was empty.", null, synced: false, 0, num),
				AutoRemoveEnabled = ((BaseUnityPlugin)this).Config.BindConfig("Auto Pin: Tombstone", "Remove on retrieval", value: true, "Death pin be removed automatically when tombstone is retrieved.", null, synced: false, 0, num)
			};
			foreach (KeyValuePair<AutoPins.AutoPinCategory, PinType> defaultPinType in AutoPins.DefaultPinTypes)
			{
				num++;
				string section = $"{num} - Auto Pin: {defaultPinType.Key.ToString()}";
				AutoPinConfigs.Add(defaultPinType.Key, new AutoPinConfig
				{
					Enabled = ((BaseUnityPlugin)this).Config.BindConfig(section, "Enabled", value: true, "Whether auto pinning is enabled.", null, synced: false, 0, num),
					Icon = ((BaseUnityPlugin)this).Config.BindConfig(section, "Icon", PinNames.PinTypeToName(defaultPinType.Value), "Which icon to create the pin with.", (AcceptableValueBase)(object)PlaceablePins.AllowedPlaceablePinNames, synced: false, 0, num)
				});
			}
			num++;
			EnableColors = ((BaseUnityPlugin)this).Config.BindConfig("Pin Colors", "Enabled", value: true, "Whether to enable custom pin colors.", null, synced: false, 10, num);
			foreach (KeyValuePair<PinType, string> defaultPinColor in PinColors.DefaultPinColors)
			{
				PinColorConfigs.Add(defaultPinColor.Key, ((BaseUnityPlugin)this).Config.BindConfig("Pin Colors", PinNames.PinTypeToName(defaultPinColor.Key), defaultPinColor.Value, "Color to use for pins of this type.", null, synced: false, 0, num));
				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();
		}
	}
	internal enum LogLevel
	{
		Low,
		Medium,
		High
	}
	internal static class Log
	{
		private static ManualLogSource logSource;

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

		internal static LogLevel VerbosityLevel => Verbosity.Value;

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

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

		internal static bool IsVerbosityHigh => Verbosity.Value >= LogLevel.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, LogLevel level = LogLevel.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;
				LogInfo(" - " + ((Object)((Component)val).gameObject).name);
				components = ((Component)val).gameObject.GetComponents<Component>();
				for (int i = 0; i < components.Length; i++)
				{
					LogComponent(components[i]);
				}
			}
		}

		internal static void LogComponent(Component compo)
		{
			LogInfo("--- " + ((object)compo).GetType().Name + ": " + ((Object)compo).name + " ---");
			PropertyInfo[] properties = ((object)compo).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty);
			foreach (PropertyInfo propertyInfo in properties)
			{
				LogInfo($" - {propertyInfo.Name} = {propertyInfo.GetValue(compo)}");
			}
			FieldInfo[] fields = ((object)compo).GetType().GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.GetProperty | BindingFlags.SetProperty);
			foreach (FieldInfo fieldInfo in fields)
			{
				LogInfo($" - {fieldInfo.Name} = {fieldInfo.GetValue(compo)}");
			}
		}
	}
}
namespace DiscoveryPins.Pins
{
	internal class AutoPinner : MonoBehaviour
	{
		private const float FindPinPrecision = 1f;

		private const float InvokeRepeatingTime = 0.1f;

		public string PinName;

		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 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_0050: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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) && !(Utils.DistanceXZ(Position, ((Component)Player.m_localPlayer).transform.position) > DiscoveryPins.Instance.AutoPinShortcutConfigs.Range.Value))
			{
				float num = Mathf.Acos((float)Math.PI / 180f * (GameCamera.instance.m_fov / 2f));
				Vector3 val = Vector3.Normalize(Position - ((Component)GameCamera.instance).transform.position);
				Vector3 val2 = Vector3.Normalize(((Character)Player.m_localPlayer).m_lookDir);
				float num2 = Vector3.Dot(val, val2);
				if (!(num2 < 0f) && !(num2 < num))
				{
					AddAutoPin();
				}
			}
		}

		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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (!IsAutoPinEnabled(out var autoPinConfig))
			{
				return false;
			}
			PinType type = PinNames.PinNameToType(autoPinConfig.Icon.Value);
			if (FindPin(Position, type, PinName) != null)
			{
				return false;
			}
			Log.LogDebug("Adding Auto Pin with name: " + PinName + ", icon: " + autoPinConfig.Icon.Value + ", pinType: " + ((object)(PinType)(ref type)).ToString());
			AddPin(Position, type, 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 = FindPin(pos, pinType, name);
			if (val != null)
			{
				Minimap.instance.RemovePin(val);
				return true;
			}
			return false;
		}

		public static PinData FindPin(Vector3 pos, PinType type = 8, string name = null)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			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;
			float num = float.MaxValue;
			foreach (var (val2, num2) in list)
			{
				if (val == null || num2 < num)
				{
					val = val2;
					num = num2;
				}
			}
			if (num > 1f)
			{
				return null;
			}
			if (!string.IsNullOrEmpty(name) && val.m_name != name)
			{
				return null;
			}
			return val;
		}
	}
	internal static class AutoPins
	{
		internal enum AutoPinCategory
		{
			Dungeon,
			Location,
			Ore
		}

		internal static Dictionary<AutoPinCategory, PinType> DefaultPinTypes = new Dictionary<AutoPinCategory, PinType>
		{
			{
				AutoPinCategory.Dungeon,
				(PinType)6
			},
			{
				AutoPinCategory.Location,
				(PinType)0
			},
			{
				AutoPinCategory.Ore,
				(PinType)2
			}
		};
	}
	[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,
				"#d43d3d"
			},
			{
				(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_0040: 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_005b: 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) && 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 LocationPins
	{
		internal static List<Location> Locations = new List<Location>();

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Location), "Awake")]
		private static void Location_AwakePostfix(Location __instance)
		{
			DungeonGenerator generator;
			if (__instance.TryGetInteriorEntrance(out var teleport, out var name))
			{
				AutoPinner.AddAutoPinner(((Component)teleport).gameObject, name, AutoPins.AutoPinCategory.Dungeon);
			}
			else if (__instance.TryGetOverworldDungeon(out generator, out name))
			{
				AutoPinner.AddAutoPinner(((Component)generator).gameObject, name, AutoPins.AutoPinCategory.Location);
			}
		}

		[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 OrePins
	{
		private static readonly List<string> OreNames = new List<string> { "Tin", "Copper", "Silver" };

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

		[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 (!Object.op_Implicit((Object)(object)prefab.transform.parent) && IsOrePrefab(prefab, out var OreName) && !OrePrefabNames.Contains(((Object)prefab).name))
				{
					OrePrefabNames.Add(((Object)prefab).name);
					AutoPinner.AddAutoPinner(prefab, OreName, AutoPins.AutoPinCategory.Ore);
				}
			}
		}

		private static void AddAutoPinnerIfOre(GameObject gameObject)
		{
			if ((Object.op_Implicit((Object)(object)gameObject.GetComponent<Destructible>()) || Object.op_Implicit((Object)(object)gameObject.GetComponent<MineRock5>())) && TryGetOreName(gameObject, out var OreName))
			{
				AutoPinner.AddAutoPinner(gameObject, OreName, AutoPins.AutoPinCategory.Ore);
			}
		}

		private static bool IsOrePrefab(GameObject gameObject, out string OreName)
		{
			if (Object.op_Implicit((Object)(object)gameObject.GetComponent<Destructible>()) || Object.op_Implicit((Object)(object)gameObject.GetComponent<MineRock5>()))
			{
				return TryGetOreName(gameObject, out OreName);
			}
			OreName = null;
			return false;
		}

		internal static bool TryGetOreName(GameObject prefab, out string OreName)
		{
			foreach (string oreName in OreNames)
			{
				if (StringExtensions.Contains(((Object)prefab).name, oreName, StringComparison.OrdinalIgnoreCase))
				{
					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();
			}
		}
	}
}
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
{
	public static class ConfigFileExtensions
	{
		internal static string ConfigFileName;

		internal static string ConfigFileFullPath;

		internal static DateTime lastRead = DateTime.MinValue;

		internal static event Action OnConfigFileReloaded;

		private static void InvokeOnConfigFileReloaded()
		{
			ConfigFileExtensions.OnConfigFileReloaded?.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> BindConfig<T>(this ConfigFile configFile, string section, string name, T value, string description, AcceptableValueBase acceptVals = null, bool synced = true, int order = 0, int sectionOrder = 0, Action<ConfigEntryBase> drawer = null, ConfigurationManagerAttributes configAttributes = null)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			string orderedSectionName = GetOrderedSectionName(section, sectionOrder);
			string extendedDescription = GetExtendedDescription(description, synced);
			if (configAttributes == null)
			{
				configAttributes = new ConfigurationManagerAttributes();
			}
			configAttributes.IsAdminOnly = synced;
			configAttributes.Order = order;
			if (drawer != null)
			{
				configAttributes.CustomDrawer = drawer;
			}
			return configFile.Bind<T>(orderedSectionName, name, value, new ConfigDescription(extendedDescription, acceptVals, new object[1] { configAttributes }));
		}

		internal static string GetOrderedSectionName(string section, int sectionOrder)
		{
			if (sectionOrder > 0)
			{
				return $"{sectionOrder} - {section}";
			}
			return section;
		}

		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 class EventExtensions
	{
		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 LocationExtensions
	{
		internal static bool TryGetInteriorEntrance(this Location location, out Teleport teleport, out string name)
		{
			teleport = null;
			name = string.Empty;
			if (!location.m_hasInterior)
			{
				return false;
			}
			for (int i = 0; i < ((Component)location).transform.childCount; i++)
			{
				if (((Component)((Component)location).transform.GetChild(i)).TryGetComponent<Teleport>(ref teleport) && teleport != null)
				{
					if (!Utility.IsNullOrWhiteSpace(teleport.m_enterText))
					{
						name = teleport.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) || generator == null)
			{
				return false;
			}
			name = ((object)(Theme)(ref generator.m_themes)).ToString();
			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 TypeExtensions
	{
		internal static List<T> GetAllPublicConstantValues<T>(this Type type)
		{
			return (from fi in type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy)
				where fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(T)
				select fi into x
				select (T)x.GetRawConstantValue()).ToList();
		}

		internal static List<T> GetAllPublicStaticValues<T>(this Type type)
		{
			return (from fi in type.GetFields(BindingFlags.Static | BindingFlags.Public)
				where fi.FieldType == typeof(T)
				select fi into x
				select (T)x.GetValue(null)).ToList();
		}
	}
	internal static class GenericExtensions
	{
		internal static T Ref<T>(this T o) where T : Object
		{
			if (!Object.op_Implicit((Object)(object)o))
			{
				return default(T);
			}
			return o;
		}
	}
	internal static class IEnumerableExtensions
	{
		internal static void Dispose(this IEnumerable<IDisposable> collection)
		{
			foreach (IDisposable item in collection)
			{
				if (item != null)
				{
					try
					{
						item.Dispose();
					}
					catch (Exception)
					{
						Log.LogWarning("Could not dispose of item");
					}
				}
			}
		}
	}
	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;
		}
	}
}