Decompiled source of Locator v1.1.0

Purps.Valheim.Locator.dll

Decompiled 5 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using HarmonyLib;
using Purps.Valheim.Framework;
using Purps.Valheim.Framework.Commands;
using Purps.Valheim.Framework.Config;
using Purps.Valheim.Framework.Data;
using Purps.Valheim.Framework.Utils;
using Purps.Valheim.Locator.Components;
using Purps.Valheim.Locator.Data;
using Purps.Valheim.Locator.Exceptions;
using Purps.Valheim.Locator.Utils;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("LocatorPlugin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LocatorPlugin")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3a28ca24-e72a-4d3b-ae30-21ff135ff61a")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Purps.Valheim.Framework
{
	public abstract class BasePlugin : BaseUnityPlugin
	{
		protected static BaseConfig BaseConfig;

		public static CommandProcessor CommandProcessor;

		private readonly string PluginGuid;

		protected BasePlugin(string pluginGuid)
		{
			PluginGuid = pluginGuid;
		}

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			CommandProcessor = new CommandProcessor();
			BaseConfig = GetConfig();
			PluginAwake();
			new Harmony(PluginGuid).PatchAll();
		}

		private void OnDestroy()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			new Harmony(PluginGuid).UnpatchSelf();
			BaseConfig.configDatas.Clear();
			BaseConfig = null;
			CommandProcessor.ClearCommands();
			CommandProcessor = null;
			PluginDestroy();
		}

		protected abstract BaseConfig GetConfig();

		protected abstract void PluginAwake();

		protected abstract void PluginDestroy();

		public static ConfigData<T> GetConfigData<T>(string key)
		{
			return BaseConfig.configDatas.GetValue<ConfigData<T>>(key);
		}

		public static void ExecuteCommand(string text)
		{
			CommandProcessor.ExecuteCommand(text);
		}

		public static List<ICommand> GetCommands()
		{
			return CommandProcessor.Commands;
		}
	}
}
namespace Purps.Valheim.Framework.Utils
{
	public static class ConsoleUtils
	{
		public static void WriteToConsole(params string[] textElements)
		{
			string text2 = "";
			if (textElements.Length == 1)
			{
				text2 = textElements.First();
			}
			else if (textElements.Length > 1)
			{
				text2 = textElements.Aggregate(text2, (string current, string text) => current + text + " ");
			}
			if (text2 != "")
			{
				Console.instance.Print(text2);
			}
		}
	}
}
namespace Purps.Valheim.Framework.Data
{
	public class GenericDictionary
	{
		private readonly Dictionary<string, object> Dictionary = new Dictionary<string, object>();

		public Dictionary<string, object>.KeyCollection Keys => Dictionary.Keys;

		public void Add<T>(string key, T value) where T : class
		{
			Dictionary.Add(key, value);
		}

		public object GetValue(string key)
		{
			return Dictionary[key];
		}

		public T GetValue<T>(string key) where T : class
		{
			return Dictionary[key] as T;
		}

		public void Clear()
		{
			Dictionary.Clear();
		}
	}
}
namespace Purps.Valheim.Framework.Config
{
	public abstract class BaseConfig
	{
		public readonly GenericDictionary configDatas = new GenericDictionary();

		protected readonly BasePlugin plugin;

		protected BaseConfig(BasePlugin plugin)
		{
			this.plugin = plugin;
		}

		protected abstract void handleCustomData<T>(ConfigData<T> configData);

		protected ConfigData<T> ReadValueFromConfig<T>(ConfigData<T> configData, bool shouldFetch = true)
		{
			if (shouldFetch)
			{
				configData.value = ((BaseUnityPlugin)plugin).Config.Bind<T>(configData.Section, configData.Key, configData.value, configData.Description).Value;
			}
			configDatas.Add(configData.Key, configData);
			return configData;
		}

		protected void CreateCommandFromConfig<T>(ConfigData<T> configData, Action<string[]> action = null)
		{
			BasePlugin.CommandProcessor.AddCommand(new Command("/" + configData.Key, configData.Description, action ?? ((Action<string[]>)delegate(string[] parameters)
			{
				SetValue(configData, parameters);
			})));
		}

		private void SetValue<T>(ConfigData<T> configData, string[] parameters)
		{
			T value = configData.value;
			if (value is bool)
			{
				object obj = value;
				bool flag = (bool)((obj is bool) ? obj : null);
				flag = !flag;
				configData.value = (T)(object)flag;
			}
			else if (value is float)
			{
				if ((float)parameters.Length > 0f && float.TryParse(parameters[0], out var result))
				{
					configData.value = (T)(object)result;
				}
			}
			else
			{
				handleCustomData(configData);
			}
		}
	}
	public class ConfigData<T>
	{
		public readonly string Description;

		public readonly string Key;

		public readonly string Section;

		public T value;

		public ConfigData(string section, string key, string description, T value)
		{
			Section = section;
			Key = key;
			Description = description;
			this.value = value;
		}

		public override string ToString()
		{
			return $"{GetType().Name}[Description={Description}, Key={Key}, Section={Section}, Value={value}]";
		}
	}
}
namespace Purps.Valheim.Framework.Commands
{
	public class Command : ICommand
	{
		public string Name { get; }

		public string Description { get; }

		public Action<string[]> Action { get; }

		public bool ShouldPrint { get; }

		public Command(string name, string description, Action<string[]> action, bool shouldPrint = true)
		{
			Name = name;
			Description = description;
			Action = action;
			ShouldPrint = shouldPrint;
		}

		public void Execute(string commandStr)
		{
			string[] array = string.Join(" ", commandStr.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries)).Split(new char[1] { ' ' }).Skip(1)
				.ToArray();
			array = Array.ConvertAll(array, (string c) => c.ToLower());
			Action(array);
		}
	}
	public class CommandProcessor
	{
		public List<ICommand> Commands { get; } = new List<ICommand>();


		public void AddCommand(ICommand command)
		{
			Commands.Add(command);
		}

		public void ClearCommands()
		{
			Commands.Clear();
		}

		public void PrintCommands(string[] parameters)
		{
			Commands.FindAll((ICommand command) => command.ShouldPrint).ForEach(delegate(ICommand command)
			{
				ConsoleUtils.WriteToConsole(command.Name + " => " + command.Description);
			});
		}

		public void ExecuteCommand(string commandStr)
		{
			Commands.FirstOrDefault((ICommand e) => e.Name.ToLower().Equals(commandStr.Split(new char[1] { ' ' }).First().ToLower()))?.Execute(commandStr.ToLower());
		}
	}
	public interface ICommand
	{
		string Name { get; }

		string Description { get; }

		Action<string[]> Action { get; }

		bool ShouldPrint { get; }

		void Execute(string commandStr);
	}
}
namespace Purps.Valheim.Locator
{
	public class LocatorConfig : BaseConfig
	{
		public LocatorConfig(BasePlugin plugin)
			: base(plugin)
		{
			CreateCommandFromConfig(ReadValueFromConfig(new ConfigData<bool>("General", "debug", "Prints useful information to configure your own pinnable item types.", value: false)));
			CreateCommandFromConfig(ReadValueFromConfig(new ConfigData<bool>("AutoPin", "pinEnabled", "Enables entity auto-pinning.", value: true)));
			CreateCommandFromConfig(ReadValueFromConfig(new ConfigData<float>("AutoPin", "pinDistance", "The allowed distance between two entities for auto-pinning.", 30f)));
			CreateCommandFromConfig(ReadValueFromConfig(new ConfigData<float>("AutoPin", "pinRayDistance", "How close the to the entity the player must be for it to be auto-pinned.", 25f)));
			CreateCommandFromConfig(ReadValueFromConfig(new ConfigData<bool>("AutoPin", "pinDestructibles", "Toggles the pinning of destructible items.", value: true)));
			CreateCommandFromConfig(ReadValueFromConfig(new ConfigData<bool>("AutoPin", "pinMineRocks", "Toggles the pinning of mineable rocks.", value: true)));
			CreateCommandFromConfig(ReadValueFromConfig(new ConfigData<bool>("AutoPin", "pinLocations", "Toggles the pinning of dungeons, caves, altars, runestones, etc.", value: true)));
			CreateCommandFromConfig(ReadValueFromConfig(new ConfigData<bool>("AutoPin", "pinPickables", "Toggle the pinning of plants and fungi", value: true)));
			CreateCommandFromConfig(ReadValueFromConfig(new ConfigData<bool>("AutoPin", "pinSpawners", "Toggles the pinning of spawners.", value: true)));
			CreateCommandFromConfig(ReadValueFromConfig(new ConfigData<bool>("AutoPin", "pinVegvisirs", "Toggles the pinning of boss runestones.", value: true)));
			CreateCommandFromConfig(ReadValueFromConfig(new ConfigData<bool>("AutoPin", "pinLeviathans", "Toggles the pinning of leviathans.", value: true)));
			CreateCommandFromConfig(ReadValueFromConfig(GetPinFilters("filterPins", "Default pin filters."), shouldFetch: false), MinimapUtils.SetPinFilters);
			ReadValueFromConfig(GetInclusionList("destructibleInclusions", "{silvervein,Silver,true}{rock3_silver,Silver,true}{MineRock_Tin,Tin,true}{rock4_copper,Copper,true}{MineRock_Obsidian,Obsidian,true}", "Inclusion list for destructible items."), shouldFetch: false);
			ReadValueFromConfig(GetInclusionList("mineRockInclusions", "{MineRock_Meteorite,Meteorite,true}", "Inclusion list for minable rocks."), shouldFetch: false);
			ReadValueFromConfig(GetInclusionList("locationInclusions", "{DrakeLorestone,Runestone,true}{TrollCave,Troll,true}{Crypt,Crypt,true}{SunkenCrypt,Crypt,true}{Grave,Grave,true}{DrakeNest,Egg,true}{Runestone,Runestone,true}{Eikthyrnir,Eikthyr,true}{GDKing,The Elder,true}{Bonemass,Bonemass,true}{Dragonqueen,Moder,true}{GoblinKing,Yagluth,true}", "Inclusion list for locations."), shouldFetch: false);
			ReadValueFromConfig(GetInclusionList("pickableInclusions", "{BlueberryBush,BlueBerry,true}{CloudberryBush,Cloudberry,true}{RaspberryBush,Raspberry,true}{Pickable_Barley,Barley,true}{Pickable_Flax,Flax,true}{Pickable_Thistle,Thistle,true}{Pickable_Mushroom,Mushroom,true}{Pickable_SeedCarrot,Carrot,true}{Pickable_Dandelion,Dandelion,true}{Pickable_SeedTurnip,Turnip,true}", "Inclusion list for pickable items."), shouldFetch: false);
			ReadValueFromConfig(GetInclusionList("spawnerInclusions", "{Spawner,Spawner,true}", "Inclusion list for spawners."), shouldFetch: false);
			ReadValueFromConfig(GetInclusionList("vegvisirInclusions", "{Vegvisir,Runestone,true}", "Inclusion list for boss runestones."), shouldFetch: false);
			ReadValueFromConfig(GetInclusionList("leviathanInclusions", "{Leviathan,Leviathan,true}", "Inclusion list for leviathans."), shouldFetch: false);
		}

		private ConfigData<string[]> GetPinFilters(string name, string description)
		{
			string value = ((BaseUnityPlugin)plugin).Config.Bind<string>("Pins", name, "", description).Value;
			string[] value2 = null;
			if (!string.IsNullOrWhiteSpace(value))
			{
				value2 = string.Join(" ", value.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries)).Split(new char[1] { ' ' });
			}
			return new ConfigData<string[]>("Pins", name, description, value2);
		}

		private ConfigData<List<TrackedObject>> GetInclusionList(string name, string defaultValue, string description)
		{
			string text = ((BaseUnityPlugin)plugin).Config.Bind<string>("Inclusions", name, "", description).Value;
			if (string.IsNullOrWhiteSpace(text))
			{
				text = defaultValue;
			}
			List<TrackedObject> value = (from i in (from Match m in new Regex("\\b[A-Za-z-'_, 0-9]+\\b").Matches(text)
					select m.Groups[0].Value).ToList()
				select GetInclusionObject(name, i)).ToList();
			return new ConfigData<List<TrackedObject>>("Inclusions", name, description, value);
		}

		private static TrackedObject GetInclusionObject(string name, string data)
		{
			string[] array = data.Split(new char[1] { ',' });
			if (array.Length == 3 && bool.TryParse(array[2], out var result))
			{
				return new TrackedObject(array[0], array[1], result);
			}
			throw new MappingException("Failed to load property " + name + ".");
		}

		protected override void handleCustomData<T>(ConfigData<T> configData)
		{
			if ((object)configData.value is string[] pinFilters)
			{
				MinimapUtils.SetPinFilters(pinFilters);
			}
		}
	}
	[BepInPlugin("purps.valheim.locator", "Locator", "1.1.0")]
	[BepInProcess("valheim.exe")]
	public class LocatorPlugin : BasePlugin
	{
		private const string PluginGuid = "purps.valheim.locator";

		private const string PluginName = "Locator";

		private const string PluginVersion = "1.1.0";

		public static readonly int CastMask = LayerMask.GetMask(new string[14]
		{
			"item", "player", "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "character", "character_net",
			"character_ghost", "hitbox", "character_noenv", "vehicle"
		});

		private static readonly GUIStyle DebugStyle = new GUIStyle();

		public static string DebugText = "";

		public static Rect DebugTextLocation = new Rect(10f, 5f, (float)Screen.width, 20f);

		public static LocatorConfig Config => (LocatorConfig)BasePlugin.BaseConfig;

		public LocatorPlugin()
			: base("purps.valheim.locator")
		{
		}

		private void Update()
		{
			DebugText = "";
			MinimapUtils.Update();
		}

		private void OnGUI()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			GuiUtils.DrawOutline(DebugTextLocation, DebugText, DebugStyle);
		}

		protected override void PluginAwake()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			DebugStyle.normal.textColor = Color.green;
			DebugStyle.fontSize = 15;
			CreateCommands();
			MinimapUtils.OnAwake();
		}

		protected override void PluginDestroy()
		{
			MinimapUtils.OnDestroy();
		}

		private void CreateCommands()
		{
			BasePlugin.CommandProcessor.AddCommand(new Command("/locator-commands", "Displays all commands provided by the Locator plugin.", BasePlugin.CommandProcessor.PrintCommands, shouldPrint: false));
			BasePlugin.CommandProcessor.AddCommand(new Command("/locatemerchant", "Pins the BlackForest Merchant on your Minimap.", delegate
			{
				WorldUtils.Locate((PinType)3, new List<Tuple<string, string>> { Tuple.Create("Vendor_BlackForest", "Merchant") }, multiple: false);
			}));
			BasePlugin.CommandProcessor.AddCommand(new Command("/locatebosses", "Pins all boss altars on your Minimap.", delegate
			{
				WorldUtils.Locate((PinType)9, new List<Tuple<string, string>>
				{
					Tuple.Create("Eikthyrnir", "Eikthyr"),
					Tuple.Create("GDKing", "The Elder"),
					Tuple.Create("Bonemass", "Bonemass"),
					Tuple.Create("Dragonqueen", "Moder"),
					Tuple.Create("GoblinKing", "Yagluth")
				}, multiple: true);
			}));
			BasePlugin.CommandProcessor.AddCommand(new Command("/listlocations", "Lists all the locations in the Console. Does not work on servers.", WorldUtils.ListLocations));
			BasePlugin.CommandProcessor.AddCommand(new Command("/listpins", "Lists all your Pins in the Console.", MinimapUtils.ListPins));
			BasePlugin.CommandProcessor.AddCommand(new Command("/clearpins", "Clears all your Pins.", MinimapUtils.ClearPins));
			BasePlugin.CommandProcessor.AddCommand(new Command("/filterpins", "Filters your minimap pins using the provided names.", MinimapUtils.SetPinFilters));
		}

		protected override BaseConfig GetConfig()
		{
			return new LocatorConfig(this);
		}
	}
}
namespace Purps.Valheim.Locator.Utils
{
	public static class GuiUtils
	{
		public static void DrawOutline(Rect position, string text, GUIStyle style)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			Color textColor = style.normal.textColor;
			style.normal.textColor = Color.black;
			float x = ((Rect)(ref position)).x;
			((Rect)(ref position)).x = x - 1f;
			GUI.Label(position, text, style);
			((Rect)(ref position)).x = ((Rect)(ref position)).x + 2f;
			GUI.Label(position, text, style);
			x = ((Rect)(ref position)).x;
			((Rect)(ref position)).x = x - 1f;
			x = ((Rect)(ref position)).y;
			((Rect)(ref position)).y = x - 1f;
			GUI.Label(position, text, style);
			((Rect)(ref position)).y = ((Rect)(ref position)).y + 2f;
			GUI.Label(position, text, style);
			x = ((Rect)(ref position)).y;
			((Rect)(ref position)).y = x - 1f;
			style.normal.textColor = textColor;
			GUI.Label(position, text, style);
		}
	}
	public static class MinimapUtils
	{
		private static readonly HashSet<Component> TrackedComponents = new HashSet<Component>();

		private static Dictionary<Type, Tuple<bool, List<TrackedObject>>> TrackedTypes => new Dictionary<Type, Tuple<bool, List<TrackedObject>>>
		{
			{
				typeof(Destructible),
				Tuple.Create(BasePlugin.GetConfigData<bool>("pinDestructibles").value, BasePlugin.GetConfigData<List<TrackedObject>>("destructibleInclusions").value)
			},
			{
				typeof(MineRock),
				Tuple.Create(BasePlugin.GetConfigData<bool>("pinMineRocks").value, BasePlugin.GetConfigData<List<TrackedObject>>("mineRockInclusions").value)
			},
			{
				typeof(Location),
				Tuple.Create(BasePlugin.GetConfigData<bool>("pinLocations").value, BasePlugin.GetConfigData<List<TrackedObject>>("locationInclusions").value)
			},
			{
				typeof(Pickable),
				Tuple.Create(BasePlugin.GetConfigData<bool>("pinPickables").value, BasePlugin.GetConfigData<List<TrackedObject>>("pickableInclusions").value)
			},
			{
				typeof(SpawnArea),
				Tuple.Create(BasePlugin.GetConfigData<bool>("pinSpawners").value, BasePlugin.GetConfigData<List<TrackedObject>>("spawnerInclusions").value)
			},
			{
				typeof(Vegvisir),
				Tuple.Create(BasePlugin.GetConfigData<bool>("pinVegvisirs").value, BasePlugin.GetConfigData<List<TrackedObject>>("vegvisirInclusions").value)
			},
			{
				typeof(Leviathan),
				Tuple.Create(BasePlugin.GetConfigData<bool>("pinLeviathans").value, BasePlugin.GetConfigData<List<TrackedObject>>("leviathanInclusions").value)
			}
		};

		public static List<PinData> MapPins
		{
			get
			{
				Traverse obj = Traverse.Create((object)Minimap.instance);
				return ((obj != null) ? obj.Field("m_pins").GetValue<List<PinData>>() : null) ?? new List<PinData>();
			}
		}

		public static string[] GetPinFilters()
		{
			return ((Component)Minimap.instance).GetComponent<CustomMinimapData>().PinFilters;
		}

		public static void SetPinFilters(string[] parameters)
		{
			if (StatusUtils.IsPlayerLoaded() && IsMinimapAvailable())
			{
				((Component)Minimap.instance).GetComponent<CustomMinimapData>().PinFilters = parameters;
			}
		}

		public static bool IsMinimapAvailable()
		{
			return (Object)(object)Minimap.instance != (Object)null;
		}

		public static void Update()
		{
			//IL_0024: 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)
			RaycastHit val = default(RaycastHit);
			if (!IsMinimapAvailable() || !BasePlugin.GetConfigData<bool>("pinEnabled").value || !Physics.Raycast(((Component)GameCamera.instance).transform.position, ((Component)GameCamera.instance).transform.forward, ref val, BasePlugin.GetConfigData<float>("pinRayDistance").value, LocatorPlugin.CastMask))
			{
				return;
			}
			foreach (Type key in TrackedTypes.Keys)
			{
				Component componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent(key, false);
				if ((Object)(object)componentInParent != (Object)null)
				{
					if (BasePlugin.GetConfigData<bool>("debug").value)
					{
						LocatorPlugin.DebugText = $"name={((Object)componentInParent).name}, type={((object)componentInParent).GetType()}";
					}
					Tuple<bool, List<TrackedObject>> valueSafe = GeneralExtensions.GetValueSafe<Type, Tuple<bool, List<TrackedObject>>>(TrackedTypes, key);
					if (valueSafe != null && valueSafe.Item1)
					{
						AddTrackedPin(componentInParent, valueSafe.Item2);
					}
				}
			}
		}

		public static void ListPins(string[] parameters)
		{
			if (!StatusUtils.IsPlayerLoaded() || !IsMinimapAvailable())
			{
				return;
			}
			List<PinData> list = MapPins;
			if (parameters != null && parameters.Length != 0)
			{
				list = list.FindAll((PinData pin) => parameters.Any(pin.m_name.ToLower().Replace(' ', '_').Contains));
			}
			list.ForEach(delegate(PinData pin)
			{
				ConsoleUtils.WriteToConsole(pin.m_name, ((object)(Vector3)(ref pin.m_pos)).ToString(), "(" + ((object)(PinType)(ref pin.m_type)).ToString() + ") " + ((Object)pin.m_icon).name);
			});
		}

		public static void AddPin(string name, Vector3 position, PinType type)
		{
			//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(position, type, name, true, false, 0L);
		}

		public static void RemovePin(PinData pin)
		{
			if (IsMinimapAvailable())
			{
				Minimap.instance.RemovePin(pin);
			}
		}

		public static void RemovePin(Vector3 position)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (TrackedComponents.RemoveWhere((Component component) => (Object)(object)component != (Object)null && (Object)(object)component.transform != (Object)null && Vector2DDistance(component.transform.position, position) < BasePlugin.GetConfigData<float>("pinDistance").value) == 0)
			{
				Minimap.instance.RemovePin(position, 1f);
			}
		}

		public static void ClearPins(string[] parameters)
		{
			if (IsMinimapAvailable())
			{
				new List<PinData>(MapPins).FindAll((PinData pin) => ((Object)pin.m_icon).name != "mapicon_start" && ((Object)pin.m_icon).name != "mapicon_trader").ForEach(RemovePin);
				TrackedComponents.Clear();
			}
		}

		public static void AddTrackedPin(Component component, List<TrackedObject> trackedObjects)
		{
			//IL_0020: 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)
			if (IsMinimapAvailable())
			{
				TrackedObject trackedObject = Track(component, trackedObjects);
				if (trackedObject != null)
				{
					AddPin(trackedObject.PinName, component.transform.position, GetPinType(component));
				}
			}
		}

		private static PinType GetPinType(Component component)
		{
			return (PinType)3;
		}

		private static TrackedObject GetTrackedObject(Component component, List<TrackedObject> typeTrackedObjects)
		{
			TrackedObject trackedObject = (from typeTrackedObject in typeTrackedObjects.FindAll((TrackedObject typeTrackedObject) => ((Object)component).name.Contains(typeTrackedObject.Name))
				orderby TrackedObject.QueryOrder(typeTrackedObject.Name, ((Object)component).name)
				select typeTrackedObject).FirstOrDefault();
			if (trackedObject == null || !trackedObject.ShouldTrack)
			{
				return null;
			}
			return trackedObject;
		}

		private static TrackedObject Track(Component component, List<TrackedObject> trackedObjects)
		{
			if (!IsMinimapAvailable())
			{
				return null;
			}
			TrackedObject trackedObject = GetTrackedObject(component, trackedObjects);
			if (trackedObject == null)
			{
				return trackedObject;
			}
			bool flag = MapPins.FindAll((PinData pin) => pin.m_name == trackedObject.PinName && Vector2DDistance(pin.m_pos, component.transform.position) < BasePlugin.GetConfigData<float>("pinDistance").value).Count == 0;
			if (TrackedComponents.Count == 0)
			{
				TrackedComponents.Add(component);
				if (!flag)
				{
					return null;
				}
				return trackedObject;
			}
			if (TrackedComponents.Where((Component t) => (Object)(object)t != (Object)null && (Object)(object)component != (Object)null && Vector3.Distance(t.transform.position, component.transform.position) < BasePlugin.GetConfigData<float>("pinDistance").value).Count() != 0)
			{
				if (!flag)
				{
					return null;
				}
				return trackedObject;
			}
			TrackedComponents.Add(component);
			return trackedObject;
		}

		private static float Vector2DDistance(Vector3 v1, Vector3 v2)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			return Mathf.Sqrt(Mathf.Pow(Mathf.Abs(v1.x - v2.x), 2f) + Mathf.Pow(Mathf.Abs(v1.z - v2.z), 2f));
		}

		public static void OnDestroy()
		{
			Minimap instance = Minimap.instance;
			Object.Destroy((Object)(object)((instance != null) ? ((Component)instance).gameObject.GetComponent<CustomMinimapData>() : null));
			TrackedComponents?.Clear();
		}

		public static void OnAwake()
		{
			Minimap instance = Minimap.instance;
			if (instance != null)
			{
				((Component)instance).gameObject.AddComponent<CustomMinimapData>();
			}
		}

		private static bool ShouldPinRender(PinData pin)
		{
			string[] pinFilters = GetPinFilters();
			if (pinFilters == null || pinFilters.Length == 0)
			{
				return true;
			}
			return pinFilters.Count((string filter) => pin.m_name.ToLower().Replace(' ', '_').Contains(filter)) != 0;
		}

		public static void FilterPins()
		{
			MapPins.ForEach(delegate(PinData pin)
			{
				bool active = ShouldPinRender(pin);
				PinNameData namePinData = pin.m_NamePinData;
				if (namePinData != null)
				{
					GameObject pinNameGameObject = namePinData.PinNameGameObject;
					if (pinNameGameObject != null)
					{
						pinNameGameObject.SetActive(active);
					}
				}
				RectTransform uiElement = pin.m_uiElement;
				if (uiElement != null)
				{
					((Component)uiElement).gameObject.SetActive(active);
				}
			});
		}
	}
	public static class StatusUtils
	{
		public static bool IsPlayerLoaded()
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				return true;
			}
			ConsoleUtils.WriteToConsole("Player must be in-game for commands to work!");
			return false;
		}

		public static bool IsPlayerOffline()
		{
			if (ZNet.instance.GetConnectedPeers().Count == 0)
			{
				return true;
			}
			ConsoleUtils.WriteToConsole("This command does not work on a server.");
			return false;
		}
	}
	public static class WorldUtils
	{
		private static readonly List<Vector3> locationPoints = GenerateLocationPoints();

		private static List<LocationInstance> MapLocations => ZoneSystem.instance.GetLocationList().ToList();

		private static List<Vector3> GenerateLocationPoints()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>();
			for (int i = 1666; i <= 10000; i += 3332)
			{
				for (double num = 0.0; num <= 360.0; num += 60.0)
				{
					float num2 = (float)((double)i * Math.Cos(num * (Math.PI / 180.0)));
					float num3 = (float)((double)i * Math.Sin(num * (Math.PI / 180.0)));
					list.Add(new Vector3(num2, 0f, num3));
				}
			}
			return list;
		}

		public static void Locate(PinType pinType, List<Tuple<string, string>> names, bool multiple)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (!StatusUtils.IsPlayerLoaded())
			{
				return;
			}
			foreach (Tuple<string, string> name in names)
			{
				if (multiple)
				{
					locationPoints.ForEach(delegate(Vector3 point)
					{
						//IL_0006: Unknown result type (might be due to invalid IL or missing references)
						//IL_000d: Unknown result type (might be due to invalid IL or missing references)
						Locate(name, point, pinType);
					});
				}
				else
				{
					Locate(name, ((Component)Player.m_localPlayer).transform.position, pinType);
				}
			}
		}

		private static void Locate(Tuple<string, string> name, Vector3 position, PinType pinType)
		{
			//IL_000b: 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)
			//IL_001a: Expected I4, but got Unknown
			Game.instance.DiscoverClosestLocation(name.Item1, position, name.Item2, (int)pinType, true, false);
		}

		public static void ListLocations(string[] parameters)
		{
			if (!StatusUtils.IsPlayerLoaded() || !StatusUtils.IsPlayerOffline())
			{
				return;
			}
			List<LocationInstance> list = MapLocations;
			if (parameters != null && parameters.Length != 0)
			{
				list = list.FindAll((LocationInstance location) => parameters.Any(location.m_location.m_prefabName.ToLower().Replace(' ', '-').Contains));
			}
			list.ForEach(delegate(LocationInstance location)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				ConsoleUtils.WriteToConsole(location.m_location.m_prefabName, ((object)(Vector3)(ref location.m_position)).ToString());
			});
		}
	}
}
namespace Purps.Valheim.Locator.Patches
{
	[HarmonyPatch(typeof(Terminal), "TryRunCommand")]
	public class TerminalPatch
	{
		[HarmonyPrefix]
		internal static bool Prefix(Terminal __instance, string text)
		{
			if (BasePlugin.GetCommands().Any((ICommand command) => text.StartsWith(command.Name)))
			{
				BasePlugin.ExecuteCommand(((TMP_InputField)__instance.m_input).text);
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Minimap), "OnMapRightClick")]
	public static class MinimapPatch
	{
		[HarmonyPostfix]
		internal static void Postfix(Minimap __instance)
		{
			//IL_001b: 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)
			MinimapUtils.RemovePin((Vector3)((object)__instance).GetType().GetMethod("ScreenToWorldPoint", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(__instance, new object[1] { Input.mousePosition }));
		}

		[HarmonyPatch(typeof(Minimap), "UpdatePins")]
		[HarmonyPostfix]
		internal static void UpdatePins(Minimap __instance)
		{
			MinimapUtils.FilterPins();
		}

		[HarmonyPatch(typeof(Minimap), "Awake")]
		[HarmonyPostfix]
		internal static void Awake(Minimap __instance)
		{
			MinimapUtils.OnAwake();
		}

		[HarmonyPatch(typeof(Minimap), "OnDestroy")]
		[HarmonyPostfix]
		internal static void OnDestroy(Minimap __instance)
		{
			MinimapUtils.OnDestroy();
		}
	}
}
namespace Purps.Valheim.Locator.Exceptions
{
	public class MappingException : Exception
	{
		public MappingException(string message)
			: base(message)
		{
		}

		public MappingException(string message, Exception inner)
			: base(message, inner)
		{
		}
	}
}
namespace Purps.Valheim.Locator.Data
{
	public class TrackedObject
	{
		public string Name { get; set; }

		public string PinName { get; set; }

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


		public TrackedObject(string name, string pinName, bool shouldTrack)
		{
			Name = name;
			PinName = pinName;
			ShouldTrack = shouldTrack;
		}

		public static int QueryOrder(string name, string query)
		{
			if (name == query)
			{
				return -1;
			}
			if (!name.Contains(query))
			{
				return 1;
			}
			return 0;
		}

		public override string ToString()
		{
			return $"{GetType().Name}[Name={Name}, PinName={PinName}, ShouldTrack={ShouldTrack}]";
		}
	}
}
namespace Purps.Valheim.Locator.Components
{
	public class CustomMinimapData : MonoBehaviour
	{
		public string[] PinFilters { get; set; } = BasePlugin.GetConfigData<string[]>("filterPins").value ?? null;

	}
}