Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Locator v1.1.0
Purps.Valheim.Locator.dll
Decompiled 2 years agousing 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; } }