Please disclose if any significant portion of your mod was created 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 Varda v1.0.0
plugins/Varda/Varda.dll
Decompiled 19 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Ezomic.Core; using HarmonyLib; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("Thijssen Software")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2026 Robbin Thijssen")] [assembly: AssemblyDescription("Dungeon entrances and portals pin themselves once you have used them.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+32c9ebb771074baf6923346adee5d6cbd690a9af")] [assembly: AssemblyProduct("Varda")] [assembly: AssemblyTitle("Varda")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Varda { internal static class DevConsole { private const float Reach = 5f; private static bool _registered; internal static void Register() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!_registered) { _registered = true; new ConsoleCommand("vardatest", "vardatest [hide | show | tag <text>] - for tests: what Varda remembers here, or hide, show or tag the nearest portal of yours within 5 metres", new ConsoleEventFailable(OnTest), true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } private static object OnTest(ConsoleEventArgs args) { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) Terminal context = args.Context; if ((Object)(object)context == (Object)null) { return "no console to answer in"; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null) { return "no world loaded"; } string text = ((args.Length > 1) ? args[1].ToLowerInvariant() : ""); if (text.Length == 0) { Report(context, localPlayer); return true; } if (text != "hide" && text != "show" && text != "tag") { return "unknown '" + args[1] + "'. Try vardatest, vardatest hide, vardatest show or vardatest tag <text>."; } if (!VardaConfig.Enabled.Value || !VardaConfig.Portals.Value) { return "Varda's Enabled or Portals is off, and the key does nothing then either"; } TeleportWorld val = Nearest(localPlayer); if ((Object)(object)val == (Object)null) { return "no portal of yours within " + 5f + " metres"; } string text2 = Where(((Component)val).transform.position); if (text == "tag") { if (args.Length < 3) { return "vardatest tag <text>"; } string text3 = string.Join(" ", args.Args, 2, args.Length - 2); val.SetText(text3); context.AddString("vardatest tag: tagged=\"" + text3 + "\" at=" + text2 + " (its pin follows on the portal's next heartbeat)"); return true; } bool flag = text == "hide"; bool flag2 = Hiding.Set(val, flag); context.AddString("vardatest " + text + ": hidden=" + (flag ? "yes" : "no") + " was=" + (flag2 ? "yes" : "no") + " at=" + text2); return true; } private static void Report(Terminal term, Player player) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) string text = "vardatest portalpins=" + Remembered.Of("portal").Count + " hiddenportals=" + Remembered.Of("hidden-portal").Count; TeleportWorld val = Nearest(player); if ((Object)(object)val == (Object)null) { term.AddString(text + " nearest=none"); return; } Vector3 position = ((Component)val).transform.position; term.AddString(text + " nearest=" + (Hiding.IsHidden(position) ? "hidden" : "shown") + " pin=" + ((Pins.At(position) != null && Remembered.Has(position, "portal")) ? "yes" : "no") + " at=" + Where(position)); } private static TeleportWorld Nearest(Player player) { //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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)player).transform.position; TeleportWorld result = null; float num = 5f; TeleportWorld[] array = Object.FindObjectsByType<TeleportWorld>((FindObjectsSortMode)0); foreach (TeleportWorld val in array) { if (Portals.Yours(val, player)) { float num2 = Utils.DistanceXZ(position, ((Component)val).transform.position); if (!(num2 >= num)) { num = num2; result = val; } } } return result; } private static string Where(Vector3 pos) { return pos.x.ToString("0.0", CultureInfo.InvariantCulture) + "," + pos.z.ToString("0.0", CultureInfo.InvariantCulture); } } internal static class Entrances { internal struct Entry { internal bool Eligible; internal Vector3 Pos; internal string Name; } internal static Entry Before(Teleport teleport, Humanoid character) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) Entry result = default(Entry); if (!VardaConfig.Enabled.Value || !VardaConfig.Dungeons.Value) { return result; } if ((Object)(object)character == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { return result; } if ((Object)(object)character != (Object)(object)Player.m_localPlayer) { return result; } if (((Character)character).InInterior()) { return result; } if ((Object)(object)teleport == (Object)null) { return result; } result.Eligible = true; result.Pos = ((Component)teleport).transform.position; result.Name = NameOf(teleport); return result; } internal unsafe static void After(Entry entry, bool moved) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) if (!entry.Eligible || !moved) { return; } float value = VardaConfig.MergeRadius.Value; if (Pins.Near(entry.Pos, value) != null) { if (VardaConfig.Verbose.Value) { VardaPlugin.Log.LogInfo((object)("A pin is already within " + value + "m of " + entry.Name + " - left alone.")); } return; } string name = (VardaConfig.NameDungeons.Value ? entry.Name : ""); if (Pins.Add(entry.Pos, VardaConfig.DungeonPinType.Value, name, Icons.Dungeon()) != null) { Remembered.Note(entry.Pos, "dungeon"); if (VardaConfig.Verbose.Value) { ManualLogSource log = VardaPlugin.Log; string name2 = entry.Name; Vector3 pos = entry.Pos; log.LogInfo((object)("Pinned " + name2 + " at " + ((object)(*(Vector3*)(&pos))/*cast due to .constrained prefix*/).ToString())); } } } private static string NameOf(Teleport teleport) { string enterText = teleport.m_enterText; if (!string.IsNullOrEmpty(enterText) && Localization.instance != null) { string text = Localization.instance.Localize(enterText); if (!string.IsNullOrEmpty(text)) { return text; } } Location componentInParent = ((Component)teleport).GetComponentInParent<Location>(); if ((Object)(object)componentInParent != (Object)null && !string.IsNullOrEmpty(((Object)componentInParent).name)) { return ((Object)componentInParent).name.Replace("(Clone)", ""); } return "Dungeon"; } } internal static class Hiding { private const string HideWords = "Hide from your map"; private const string ShowWords = "Show on your map"; private static MethodInfo _takeInput; private static bool _triedTakeInput; internal static bool IsHidden(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Remembered.Has(pos, "hidden-portal"); } internal static void Listen() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (!VardaConfig.Enabled.Value || !VardaConfig.Portals.Value || !Pressed(VardaConfig.HidePortalKey.Value)) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !Listening(localPlayer)) { return; } GameObject hoverObject = ((Humanoid)localPlayer).GetHoverObject(); if (!((Object)(object)hoverObject == (Object)null)) { TeleportWorld componentInParent = hoverObject.GetComponentInParent<TeleportWorld>(); if (Portals.Yours(componentInParent, localPlayer)) { Set(componentInParent, !IsHidden(((Component)componentInParent).transform.position)); } } } internal unsafe static bool Set(TeleportWorld portal, bool hide) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)portal).transform.position; bool flag = IsHidden(position); if (hide) { if (!flag) { Remembered.Note(position, "hidden-portal"); } PinData val = TakeOff(position); if (VardaConfig.Verbose.Value) { ManualLogSource log = VardaPlugin.Log; Vector3 val2 = position; log.LogInfo((object)("Hid your portal at " + ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString() + " from your map" + ((val == null) ? "; it had no pin of Varda's on it to take off." : (" and took its pin" + (string.IsNullOrEmpty(val.m_name) ? "" : (" \"" + val.m_name + "\"")) + " off.")))); } } else { Remembered.Drop(position, "hidden-portal"); if (VardaConfig.Verbose.Value) { ManualLogSource log2 = VardaPlugin.Log; Vector3 val2 = position; log2.LogInfo((object)("Showed your portal at " + ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString() + " on your map again. Its pin comes back on the portal's next heartbeat.")); } } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, hide ? "Portal hidden from your map" : "Portal shown on your map", 0, (Sprite)null, false); } return flag; } internal unsafe static void KeepOff(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (Remembered.Has(pos, "portal") && TakeOff(pos) != null && VardaConfig.Verbose.Value) { ManualLogSource log = VardaPlugin.Log; Vector3 val = pos; log.LogInfo((object)("Took the pin off your hidden portal at " + ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString() + " again. It came back with a map saved before you hid the portal.")); } } private static PinData TakeOff(Vector3 pos) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) PinData result = null; foreach (Vector3 item in Remembered.Of("portal")) { if (!(Utils.DistanceXZ(item, pos) >= 0.1f)) { PinData val = Pins.At(item); if (val != null) { Pins.Remove(val); result = val; } Remembered.Forget(item, "portal"); } } return result; } internal static string HoverLine(TeleportWorld portal) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (!VardaConfig.Enabled.Value || !VardaConfig.Portals.Value) { return ""; } KeyCode value = VardaConfig.HidePortalKey.Value; if ((int)value == 0 || !Bound()) { return ""; } if (!Portals.Yours(portal, Player.m_localPlayer)) { return ""; } return "\n[<color=yellow><b>" + KeyName(value) + "</b></color>] " + (IsHidden(((Component)portal).transform.position) ? "Show on your map" : "Hide from your map"); } private unsafe static string KeyName(KeyCode key) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) string text = null; try { text = ZInput.KeyCodeToDisplayName(key); } catch (Exception) { } if (string.IsNullOrEmpty(text) || text.StartsWith("$", StringComparison.Ordinal)) { return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); } return text; } private static bool Pressed(KeyCode key) { //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) if ((int)key == 0) { return false; } if (!ZInput.GetKeyDown(key, false)) { return false; } if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) { return false; } if (!Console.IsVisible()) { return !TextInput.IsVisible(); } return false; } private static bool Listening(Player player) { if (Game.IsPaused() || Hud.InRadial()) { return false; } return TakesInput(player); } private static bool TakesInput(Player player) { if (!Bound()) { return false; } try { return (bool)_takeInput.Invoke(player, null); } catch (Exception) { return false; } } private static bool Bound() { if (_triedTakeInput) { return _takeInput != null; } _triedTakeInput = true; try { _takeInput = AccessTools.Method(typeof(Player), "TakeInput", Type.EmptyTypes, (Type[])null); } catch (Exception) { _takeInput = null; } if (_takeInput != null && _takeInput.ReturnType == typeof(bool)) { return true; } _takeInput = null; VardaPlugin.Log.LogWarning((object)"Cannot find Player.TakeInput, the game's own test for whether a keystroke is meant for the player. HidePortalKey does nothing and portals do not offer it; pins are unaffected."); return false; } } internal static class IconDump { private static bool _done; internal static void Reset() { _done = false; } internal unsafe static void Run() { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) if (_done || !VardaConfig.DumpIcons.Value) { return; } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return; } _done = true; string text = Path.Combine(Path.Combine(Paths.ConfigPath, "Varda"), "icons"); try { Directory.CreateDirectory(text); } catch (Exception ex) { VardaPlugin.Log.LogWarning((object)("Cannot write " + text + ": " + ex.Message)); return; } HashSet<string> hashSet = new HashSet<string>(); foreach (SpriteData icon in instance.m_icons) { PinType name = icon.m_name; Record(text, hashSet, ((object)(*(PinType*)(&name))/*cast due to .constrained prefix*/).ToString(), icon.m_icon); } foreach (LocationSpriteData locationIcon in instance.m_locationIcons) { Record(text, hashSet, "location_" + locationIcon.m_name, locationIcon.m_icon); } VardaPlugin.Log.LogInfo((object)("Icon dump finished: " + hashSet.Count + " sheet(s) in " + text + ". Turn DumpIcons off again.")); } private static void Record(string folder, HashSet<string> written, string slot, Sprite sprite) { //IL_002c: 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) if ((Object)(object)sprite == (Object)null) { VardaPlugin.Log.LogInfo((object)(" " + slot + " has no sprite.")); return; } Texture2D texture = sprite.texture; Rect textureRect = sprite.textureRect; VardaPlugin.Log.LogInfo((object)(" " + slot + " sprite=" + ((Object)sprite).name + " sheet=" + (((Object)(object)texture == (Object)null) ? "none" : ((Object)texture).name) + " rect=" + (int)((Rect)(ref textureRect)).x + "," + (int)((Rect)(ref textureRect)).y + "," + (int)((Rect)(ref textureRect)).width + "," + (int)((Rect)(ref textureRect)).height + " pixelsPerUnit=" + sprite.pixelsPerUnit)); if ((Object)(object)texture == (Object)null) { return; } string text = (string.IsNullOrEmpty(((Object)texture).name) ? "sheet" : ((Object)texture).name); if (!written.Add(text)) { return; } try { byte[] array = Encode(texture); if (array != null) { File.WriteAllBytes(Path.Combine(folder, text + ".png"), array); } } catch (Exception ex) { VardaPlugin.Log.LogWarning((object)("Could not write " + text + ".png: " + ex.Message)); } } private static byte[] Encode(Texture2D texture) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2); RenderTexture active = RenderTexture.active; Texture2D val = null; try { Graphics.Blit((Texture)(object)texture, temporary); RenderTexture.active = temporary; val = new Texture2D(((Texture)texture).width, ((Texture)texture).height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), 0, 0); val.Apply(); return EncodePng(val); } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } } private static byte[] EncodePng(Texture2D texture) { Type type = AccessTools.TypeByName("UnityEngine.ImageConversion"); if (type == null) { return null; } MethodInfo methodInfo = AccessTools.Method(type, "EncodeToPNG", new Type[1] { typeof(Texture2D) }, (Type[])null); if (methodInfo == null) { return null; } return (byte[])methodInfo.Invoke(null, new object[1] { texture }); } } internal static class Icons { private static readonly string[] DungeonDonors = new string[5] { "Crypt2", "Crypt3", "Crypt4", "SunkenCrypt4", "MountainCave02" }; private static Sprite _dungeon; private static Sprite _portal; private static bool _resolved; private static readonly Dictionary<string, Sprite> Loaded = new Dictionary<string, Sprite>(); internal static void Reset() { _dungeon = null; _portal = null; _resolved = false; } internal static void Warm() { Resolve(); } internal static Sprite Dungeon() { Resolve(); return _dungeon; } internal static Sprite Portal() { Resolve(); return _portal; } internal static Sprite Named(string name) { if (string.IsNullOrEmpty(name)) { return null; } return FromFile(name.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ? name : (name + ".png")); } private unsafe static void Resolve() { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (_resolved) { return; } Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return; } _resolved = true; _dungeon = FromFile(VardaConfig.DungeonIcon.Value); if ((Object)(object)_dungeon == (Object)null) { _dungeon = Borrow(instance); } _portal = FromFile(VardaConfig.PortalIcon.Value); if (!VardaConfig.Verbose.Value) { return; } foreach (SpriteData icon in instance.m_icons) { ManualLogSource log = VardaPlugin.Log; PinType name = icon.m_name; log.LogInfo((object)(" pin type " + ((object)(*(PinType*)(&name))/*cast due to .constrained prefix*/).ToString() + " wears " + (((Object)(object)icon.m_icon == (Object)null) ? "nothing" : ((Object)icon.m_icon).name))); } VardaPlugin.Log.LogInfo((object)(" " + instance.m_locationIcons.Count + " location icons, dungeon sprite is " + (((Object)(object)_dungeon == (Object)null) ? "the plain pin" : ((Object)_dungeon).name) + ", portal sprite is " + (((Object)(object)_portal == (Object)null) ? "the plain pin" : ((Object)_portal).name))); } private static Sprite Borrow(Minimap map) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) string[] dungeonDonors = DungeonDonors; foreach (string text in dungeonDonors) { foreach (LocationSpriteData locationIcon in map.m_locationIcons) { if (locationIcon.m_name == text && (Object)(object)locationIcon.m_icon != (Object)null) { return locationIcon.m_icon; } } } VardaPlugin.Log.LogInfo((object)("No dungeon icon to borrow - dungeon pins will wear the plain " + ((object)VardaConfig.DungeonPinType.Value/*cast due to .constrained prefix*/).ToString() + " icon. Drop a dungeon.png beside Varda.dll to give them their own.")); return null; } private static Sprite FromFile(string fileName) { //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) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(fileName)) { return null; } if (Loaded.TryGetValue(fileName, out var value)) { return value; } Loaded[fileName] = null; string directoryName = Path.GetDirectoryName(typeof(Icons).Assembly.Location); if (string.IsNullOrEmpty(directoryName)) { return null; } string path = Path.Combine(directoryName, fileName); if (!File.Exists(path)) { VardaPlugin.Log.LogInfo((object)("No " + fileName + " beside the DLL - falling back for that pin. This is the normal state until an icon is drawn; it is not an error.")); return null; } try { byte[] data = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false) { filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)1 }; if (!LoadPng(val, data)) { Object.Destroy((Object)(object)val); VardaPlugin.Log.LogWarning((object)(fileName + " is not a PNG this can read.")); return null; } Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); ((Object)val2).name = "Varda_" + Path.GetFileNameWithoutExtension(fileName); Loaded[fileName] = val2; return val2; } catch (Exception ex) { VardaPlugin.Log.LogWarning((object)("Could not read " + fileName + ": " + ex.Message)); return null; } } private static bool LoadPng(Texture2D texture, byte[] data) { Type type = AccessTools.TypeByName("UnityEngine.ImageConversion"); if (type == null) { return false; } MethodInfo methodInfo = AccessTools.Method(type, "LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }, (Type[])null) ?? AccessTools.Method(type, "LoadImage", new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }, (Type[])null); if (methodInfo == null) { return false; } object[] parameters = ((methodInfo.GetParameters().Length != 3) ? new object[2] { texture, data } : new object[3] { texture, data, false }); return (bool)methodInfo.Invoke(null, parameters); } } internal static class Pins { private static FieldRef<Minimap, List<PinData>> _pinList; private static bool _tried; internal const float SameSpot = 0.1f; private static List<PinData> All() { Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return null; } if (!_tried) { _tried = true; try { _pinList = AccessTools.FieldRefAccess<Minimap, List<PinData>>("m_pins"); } catch (Exception ex) { VardaPlugin.Log.LogWarning((object)("Cannot read the map's pin list (" + ex.GetType().Name + "). Pins will still be added; what is lost is the check that stops a second pin landing on one that is already there.")); } } if (_pinList == null) { return null; } try { return _pinList.Invoke(instance); } catch (Exception) { return null; } } internal static PinData Near(Vector3 pos, float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Near(pos, radius, null); } internal static PinData Near(Vector3 pos, float radius, Predicate<PinData> skip) { //IL_0024: 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) List<PinData> list = All(); if (list == null) { return null; } foreach (PinData item in list) { if (item.m_save && !(Utils.DistanceXZ(pos, item.m_pos) >= radius) && (skip == null || !skip(item))) { return item; } } return null; } internal static PinData At(Vector3 pos) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) List<PinData> list = All(); if (list == null) { return null; } PinData result = null; float num = 0.1f; foreach (PinData item in list) { if (item.m_save && item.m_ownerID == 0L) { float num2 = Utils.DistanceXZ(pos, item.m_pos); if (!(num2 >= num)) { num = num2; result = item; } } } return result; } internal static PinData Add(Vector3 pos, PinType type, string name, Sprite icon) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) Minimap instance = Minimap.instance; if ((Object)(object)instance == (Object)null) { return null; } PinData obj = instance.AddPin(pos, type, name ?? "", true, false, 0L, default(PlatformUserID)); Dress(obj, icon); return obj; } internal static void Dress(PinData pin, Sprite icon) { if (pin != null && !((Object)(object)icon == (Object)null)) { pin.m_icon = icon; if ((Object)(object)pin.m_iconElement != (Object)null) { pin.m_iconElement.sprite = icon; } } } internal static void Remove(PinData pin) { Minimap instance = Minimap.instance; if (!((Object)(object)instance == (Object)null) && pin != null) { instance.RemovePin(pin); } } } internal static class Portals { private const float SettleSeconds = 10f; private const float SweepEvery = 1f; private static ZDOMan _watched; private static float _nextSweep; private static readonly Dictionary<Vector2, float> SettledSince = new Dictionary<Vector2, float>(); private static readonly HashSet<Vector2> SettledNow = new HashSet<Vector2>(); private static readonly List<Vector2> NoLongerSettled = new List<Vector2>(); private static readonly List<ZDO> Nearby = new List<ZDO>(); private static readonly Predicate<PinData> PortalPin = (PinData pin) => Remembered.Has(pin.m_pos, "portal"); private const string DestroyedHere = "was destroyed while your game had it loaded"; private const string FoundGone = "was not there once the area around it had settled"; internal unsafe static void Tick(TeleportWorld portal) { //IL_0050: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) if (!VardaConfig.Enabled.Value || !VardaConfig.Portals.Value || (Object)(object)portal == (Object)null) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)Minimap.instance == (Object)null || !Yours(portal, localPlayer)) { return; } Vector3 position = ((Component)portal).transform.position; if (Hiding.IsHidden(position)) { Hiding.KeepOff(position); return; } string text = portal.GetText(); if (text == null) { text = ""; } bool flag = Remembered.Has(position, "portal"); if (flag) { PinData val = Pins.At(position); if (val != null) { if (val.m_name != text) { Rename(val, text); } return; } } float value = VardaConfig.PortalMergeRadius.Value; if (Pins.Near(position, value, PortalPin) == null && Pins.Add(position, VardaConfig.PortalPinType.Value, text, Icons.Portal()) != null) { if (!flag) { Remembered.Note(position, "portal"); } if (VardaConfig.Verbose.Value) { ManualLogSource log = VardaPlugin.Log; Vector3 val2 = position; log.LogInfo((object)("Pinned your portal at " + ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString() + ((text.Length == 0) ? " (no tag yet)" : (" as \"" + text + "\"")))); } } } internal static bool Yours(TeleportWorld portal, Player player) { if ((Object)(object)portal == (Object)null || (Object)(object)player == (Object)null) { return false; } ZNetView val = default(ZNetView); if (!((Component)portal).TryGetComponent<ZNetView>(ref val) || !val.IsValid()) { return false; } Piece val2 = default(Piece); if (!((Component)portal).TryGetComponent<Piece>(ref val2)) { return false; } long creator = val2.GetCreator(); if (creator != 0L) { return creator == player.GetPlayerID(); } return false; } private static void Rename(PinData own, string tag) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) Pins.Remove(own); if (Pins.Add(own.m_pos, VardaConfig.PortalPinType.Value, tag, Icons.Portal()) != null && VardaConfig.Verbose.Value) { VardaPlugin.Log.LogInfo((object)("Renamed a portal pin to \"" + tag + "\"")); } } internal static void Watch() { ZDOMan instance = ZDOMan.instance; if (instance != null && instance != _watched) { instance.m_onZDODestroyed = (Action<ZDO>)Delegate.Combine(instance.m_onZDODestroyed, new Action<ZDO>(Destroyed)); _watched = instance; SettledSince.Clear(); } } private static void Destroyed(ZDO zdo) { //IL_004b: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) try { if (!Active() || zdo == null) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)Minimap.instance == (Object)null) { return; } long playerID = localPlayer.GetPlayerID(); if (!IsYourPortal(zdo, playerID)) { return; } Vector3 position = zdo.GetPosition(); foreach (Vector3 item in Remembered.Of("portal")) { if (!(Utils.DistanceXZ(item, position) >= 0.1f)) { Resolve(item, playerID, zdo, "was destroyed while your game had it loaded"); } } foreach (Vector3 item2 in Remembered.Of("hidden-portal")) { if (!(Utils.DistanceXZ(item2, position) >= 0.1f)) { ForgetHidden(item2, playerID, zdo, "was destroyed while your game had it loaded"); } } } catch (Exception ex) { VardaPlugin.Log.LogWarning((object)("Could not check a destroyed object for a portal pin (" + ex.GetType().Name + ": " + ex.Message + "). The pin, if there was one, stays on the map.")); } } private unsafe static void Resolve(Vector3 spot, long me, ZDO dying, string why) { //IL_0000: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_0083: Unknown result type (might be due to invalid IL or missing references) if (Stands(spot, me, dying)) { return; } PinData val = Pins.At(spot); if (val != null) { Pins.Remove(val); } if (Remembered.Forget(spot, "portal") && VardaConfig.Verbose.Value) { if (val != null) { ManualLogSource log = VardaPlugin.Log; string[] obj = new string[7] { "Took your portal pin", string.IsNullOrEmpty(val.m_name) ? "" : (" \"" + val.m_name + "\""), " off the map at ", null, null, null, null }; Vector3 val2 = spot; obj[3] = ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj[4] = ": the portal "; obj[5] = why; obj[6] = ". Varda no longer remembers it."; log.LogInfo((object)string.Concat(obj)); } else { ManualLogSource log2 = VardaPlugin.Log; string[] obj2 = new string[5] { "Forgot your portal at ", null, null, null, null }; Vector3 val2 = spot; obj2[1] = ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj2[2] = ": the portal "; obj2[3] = why; obj2[4] = ", and its pin had already been taken off by hand."; log2.LogInfo((object)string.Concat(obj2)); } } } private unsafe static void ForgetHidden(Vector3 spot, long me, ZDO dying, string why) { //IL_0000: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (!Stands(spot, me, dying) && Remembered.Drop(spot, "hidden-portal") && VardaConfig.Verbose.Value) { ManualLogSource log = VardaPlugin.Log; string[] obj = new string[5] { "Forgot that you hid your portal at ", null, null, null, null }; Vector3 val = spot; obj[1] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[2] = ": the portal "; obj[3] = why; obj[4] = ". A portal built there again gets a pin."; log.LogInfo((object)string.Concat(obj)); } } private static bool IsYourPortal(ZDO zdo, long me) { long num = zdo.GetLong(ZDOVars.s_creator, 0L); if (num == 0L || num != me) { return false; } ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return false; } GameObject prefab = instance.GetPrefab(zdo.GetPrefab()); if ((Object)(object)prefab == (Object)null) { return false; } TeleportWorld val = default(TeleportWorld); return prefab.TryGetComponent<TeleportWorld>(ref val); } private static bool Stands(Vector3 spot, long me, ZDO dying) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) ZDOMan instance = ZDOMan.instance; if (instance == null || (Object)(object)ZoneSystem.instance == (Object)null) { return true; } Nearby.Clear(); instance.FindSectorObjects(ZoneSystem.GetZone(spot), new SimulationDistance(1, 0, true), Nearby, (List<ZDO>)null); foreach (ZDO item in Nearby) { if (item != null && item != dying && !(Utils.DistanceXZ(item.GetPosition(), spot) >= 0.1f) && IsYourPortal(item, me)) { return true; } } return false; } internal static void Sweep() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; if (time < _nextSweep) { return; } _nextSweep = time + 1f; if (!Active()) { SettledSince.Clear(); return; } if ((Object)(object)Game.instance == (Object)null || Game.instance.IsShuttingDown() || (int)ZNet.GetConnectionStatus() != 2) { SettledSince.Clear(); return; } ZDOMan instance = ZDOMan.instance; if (instance == null || instance != _watched) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)Minimap.instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null) { return; } if (((Character)localPlayer).IsTeleporting()) { SettledSince.Clear(); return; } Vector3 referencePosition = ZNet.instance.GetReferencePosition(); long playerID = localPlayer.GetPlayerID(); SettledNow.Clear(); foreach (Vector3 item in Remembered.Of("portal")) { if (Due(item, referencePosition, time)) { Resolve(item, playerID, null, "was not there once the area around it had settled"); } } foreach (Vector3 item2 in Remembered.Of("hidden-portal")) { if (Due(item2, referencePosition, time)) { ForgetHidden(item2, playerID, null, "was not there once the area around it had settled"); } } NoLongerSettled.Clear(); foreach (Vector2 key in SettledSince.Keys) { if (!SettledNow.Contains(key)) { NoLongerSettled.Add(key); } } foreach (Vector2 item3 in NoLongerSettled) { SettledSince.Remove(item3); } } private static bool Due(Vector3 spot, Vector3 centre, float now) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (!Settled(spot, centre)) { return false; } Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(spot.x, spot.z); SettledNow.Add(val); if (!SettledSince.TryGetValue(val, out var value)) { SettledSince[val] = now; return false; } return now - value >= 10f; } private static bool Settled(Vector3 spot, Vector3 centre) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (ZNetScene.InActiveArea(spot, centre)) { return ZNetScene.instance.IsAreaReady(spot); } return false; } private static bool Active() { if (VardaConfig.Enabled.Value && VardaConfig.Portals.Value) { return VardaConfig.RemoveDestroyedPortals.Value; } return false; } } internal static class Remembered { private struct Entry { internal string Icon; internal float X; internal float Z; } internal const string Dungeon = "dungeon"; internal const string Portal = "portal"; internal const string HiddenPortal = "hidden-portal"; private static readonly List<Entry> Entries = new List<Entry>(); private static string _path; private static readonly List<Entry> Leaving = new List<Entry>(); private static readonly List<Entry> Taken = new List<Entry>(); private static ZDOMan _session; internal static void Load() { string text = PathFor(); if (text == null || text != _path || ZDOMan.instance != _session) { Leaving.Clear(); Taken.Clear(); } _session = ZDOMan.instance; Entries.Clear(); _path = text; if (text == null || !File.Exists(text)) { return; } List<Entry> list = new List<Entry>(Leaving); list.AddRange(Taken); try { string[] array = File.ReadAllLines(text); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ';' }); if (array2.Length != 3) { continue; } string text2 = array2[0].Trim().ToLowerInvariant(); if (text2.Length != 0 && float.TryParse(array2[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array2[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { Entry entry = new Entry { Icon = text2, X = result, Z = result2 }; if (!Departing(entry, list)) { Entries.Add(entry); } } } } catch (Exception ex) { VardaPlugin.Log.LogWarning((object)("Could not read " + text + " (" + ex.Message + "). Pins already on the map keep their plain icons this session; nothing is lost from the map.")); } if (VardaConfig.Verbose.Value) { VardaPlugin.Log.LogInfo((object)("Remembering " + Entries.Count + " pins from " + text)); } } internal static void Note(Vector3 pos, string icon) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(icon)) { Entries.Add(new Entry { Icon = icon, X = pos.x, Z = pos.z }); Save(); } } internal static void Apply() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (Entries.Count == 0) { return; } int num = 0; for (int num2 = Entries.Count - 1; num2 >= 0; num2--) { Entry entry = Entries[num2]; if (!(entry.Icon == "hidden-portal")) { PinData val = Pins.At(new Vector3(entry.X, 0f, entry.Z)); if (val == null) { Entries.RemoveAt(num2); } else { Sprite val2 = SpriteFor(entry.Icon); if (!((Object)(object)val2 == (Object)null)) { Pins.Dress(val, val2); num++; } } } } Save(); if (VardaConfig.Verbose.Value) { VardaPlugin.Log.LogInfo((object)("Put Varda's icons back on " + num + " pins.")); } } internal static List<Vector3> Of(string icon) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) List<Vector3> list = new List<Vector3>(); foreach (Entry entry in Entries) { if (entry.Icon == icon) { list.Add(new Vector3(entry.X, 0f, entry.Z)); } } return list; } internal static bool Forget(Vector3 pos, string icon) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) Entry b = new Entry { Icon = icon, X = pos.x, Z = pos.z }; bool result = false; for (int num = Entries.Count - 1; num >= 0; num--) { if (Same(Entries[num], b)) { Leaving.Add(Entries[num]); Entries.RemoveAt(num); result = true; } } return result; } internal static bool Drop(Vector3 pos, string icon) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) bool flag = false; for (int num = Entries.Count - 1; num >= 0; num--) { Entry entry = Entries[num]; if (!(entry.Icon != icon)) { float num2 = entry.X - pos.x; float num3 = entry.Z - pos.z; if (!(num2 * num2 + num3 * num3 >= 0.010000001f)) { Entries.RemoveAt(num); flag = true; } } } if (flag) { Save(); } return flag; } internal static void MapTaken() { Taken.AddRange(Leaving); Leaving.Clear(); } internal static void MapWritten() { if (Taken.Count != 0) { Taken.Clear(); Save(); } } private static bool Departing(Entry entry, List<Entry> unclaimed) { for (int i = 0; i < unclaimed.Count; i++) { if (Same(unclaimed[i], entry)) { unclaimed.RemoveAt(i); return true; } } return false; } private static bool Same(Entry a, Entry b) { if (a.Icon == b.Icon && Mathf.Abs(a.X - b.X) <= 0.01f) { return Mathf.Abs(a.Z - b.Z) <= 0.01f; } return false; } internal static bool Has(Vector3 pos, string icon) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) foreach (Entry entry in Entries) { if (!(entry.Icon != icon)) { float num = entry.X - pos.x; float num2 = entry.Z - pos.z; if (num * num + num2 * num2 < 0.010000001f) { return true; } } } return false; } private static Sprite SpriteFor(string icon) { if (icon == "dungeon") { return Icons.Dungeon(); } if (icon == "portal") { return Icons.Portal(); } return Icons.Named(icon); } private static void Save() { if (_path == null) { return; } try { StringBuilder stringBuilder = new StringBuilder(); List<Entry>[] array = new List<Entry>[3] { Entries, Leaving, Taken }; for (int i = 0; i < array.Length; i++) { foreach (Entry item in array[i]) { StringBuilder stringBuilder2 = stringBuilder.Append(item.Icon).Append(';'); float x = item.X; StringBuilder stringBuilder3 = stringBuilder2.Append(x.ToString("R", CultureInfo.InvariantCulture)).Append(';'); x = item.Z; stringBuilder3.Append(x.ToString("R", CultureInfo.InvariantCulture)).Append('\n'); } } string directoryName = Path.GetDirectoryName(_path); if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } File.WriteAllText(_path, stringBuilder.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); } catch (Exception ex) { VardaPlugin.Log.LogWarning((object)("Could not write " + _path + " (" + ex.Message + "). The pins are on the map either way; what is at risk is their icons after the next load.")); } } private static string PathFor() { if ((Object)(object)ZNet.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { return null; } string text = Safe(ZNet.instance.GetWorldName()); string text2 = Safe(Player.m_localPlayer.GetPlayerName()); if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(text2)) { return null; } return Path.Combine(Path.Combine(Paths.ConfigPath, "Varda"), text + "." + text2 + ".txt"); } private static string Safe(string name) { if (string.IsNullOrEmpty(name)) { return null; } char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); foreach (char oldChar in invalidFileNameChars) { name = name.Replace(oldChar, '_'); } return name.Replace('.', '_'); } } internal static class VardaConfig { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> Dungeons; internal static ConfigEntry<bool> Portals; internal static ConfigEntry<bool> RemoveDestroyedPortals; internal static ConfigEntry<KeyCode> HidePortalKey; internal static ConfigEntry<bool> NameDungeons; internal static ConfigEntry<PinType> DungeonPinType; internal static ConfigEntry<PinType> PortalPinType; internal static ConfigEntry<string> DungeonIcon; internal static ConfigEntry<string> PortalIcon; internal static ConfigEntry<float> MergeRadius; internal static ConfigEntry<float> PortalMergeRadius; internal static ConfigEntry<bool> DumpIcons; internal static ConfigEntry<bool> Verbose; internal static void Bind(ConfigFile cfg) { Enabled = cfg.Bind<bool>("Varda", "Enabled", true, "Off leaves the plugin loaded and stops it adding anything to the map. Pins already on the map stay - they are ordinary map pins and nothing removes them but you."); Dungeons = cfg.Bind<bool>("Varda", "Dungeons", true, "Pin a burial chamber, cave, crypt or mine when you GO IN. Walking past the door does nothing - the pin is a record of where you have been, never a hint about where something is."); Portals = cfg.Bind<bool>("Varda", "Portals", true, "Pin portals you built, labelled with whatever you tagged them. Portals built by other players are never pinned; you would be reading their map."); RemoveDestroyedPortals = cfg.Bind<bool>("Varda", "RemoveDestroyedPortals", true, "Take a portal's pin off your map when that portal is destroyed, by your hammer, by damage or by anybody else. If it went while you were far away, the pin comes off the next time you stand near where it was, once the area has finished loading. Walking out of sight of a portal never counts. Only pins Varda put on portals you built: a pin you placed by hand is never touched, and neither is a dungeon pin. A portal you hid with HidePortalKey is forgotten the same way, so a new portal built on its spot gets a pin. Does nothing while Portals is off."); HidePortalKey = cfg.Bind<KeyCode>("Varda", "HidePortalKey", (KeyCode)104, "Look at a portal you built and press this to take its pin off your map, and press it again to put the pin back. The portal's hover text names the key and says which it will do. It is yours alone: nobody else's map changes and the portal itself is untouched, and it is remembered per character, per world and per portal. A pin you placed by hand is never touched. H because neither the game nor any of this author's other mods binds it; Shift+E would have been the natural gesture, but Skra's portal settings already use it. None takes away the key and its hover line, but a portal you already hid stays hidden until you bind a key again and press it on that portal. Does nothing while Portals is off."); NameDungeons = cfg.Bind<bool>("Varda", "NameDungeons", false, "Put the dungeon's own name under its pin - the same name the banner shows as you go in. Off, because the icon already says what it is. On is worth it if you want to tell two crypts apart without opening them."); DungeonPinType = cfg.Bind<PinType>("Varda", "DungeonPinType", (PinType)3, "Which of the five hand-placed pin types a dungeon pin is saved as. This is what it turns into if you uninstall Varda, and which filter row hides it. The five are Icon0 fire, Icon1 house, Icon2 hammer, Icon3 plain marker, Icon4 portal."); PortalPinType = cfg.Bind<PinType>("Varda", "PortalPinType", (PinType)6, "The same, for portal pins. Icon4 is the game's own portal icon, which is already the right picture - there is no reason to change this one."); DungeonIcon = cfg.Bind<string>("Varda", "DungeonIcon", "dungeon.png", "PNG beside Varda.dll to draw dungeon pins with. Missing file, or empty, falls back to a crypt icon borrowed from the game's own map, which Valheim 1.0 does not carry, so in practice to the plain pin above. Nothing here is ever fatal."); PortalIcon = cfg.Bind<string>("Varda", "PortalIcon", "", "PNG beside Varda.dll to draw portal pins with. Empty by default because PortalPinType is already the game's portal icon, which is the right picture. Only worth setting if you want portals to stand out from the ones you pin by hand."); MergeRadius = cfg.Bind<float>("Varda", "MergeRadius", 8f, "Metres, for dungeons. A dungeon pin is not added when a pin already sits this close to the door, whoever put it there. So re-entering a crypt does not stack pins, and a pin you placed by hand on the door is left alone rather than doubled. Portals have their own setting, PortalMergeRadius."); PortalMergeRadius = cfg.Bind<float>("Varda", "PortalMergeRadius", 1f, "Metres, for portals. A portal of yours gets no pin of its own while another pin already sits this close to it, such as one you placed on it by hand, so the two are not doubled. The pins Varda put on your other portals never count, so portals built side by side each keep their own. One metre is what the game itself treats as the same spot for a pin, and in an ordinary row, with portals a few metres apart, a pin that close stands in only for the portal it is on. Raising it respects hand pins placed less exactly, but keep it under half the gap between your portals, or one pin will leave its neighbours without theirs."); DumpIcons = cfg.Bind<bool>("Varda", "DumpIcons", false, "Write the game's own map pin art to BepInEx/config/Varda/icons/ once, and log where each pin's picture sits on the sheet. For drawing an icon that matches; turn it off again afterwards. It writes whole sheets, not cropped pins, because cropping needs a vertical flip that is easy to get silently wrong."); Verbose = cfg.Bind<bool>("Varda", "Verbose", false, "Write every pin added, every icon resolved and the name of every sprite the map carries to BepInEx/LogOutput.log. The sprite list is how you find out which PinType wears which icon, which is asset data and not readable anywhere else."); } } internal static class VardaPatches { [HarmonyPrefix] [HarmonyPatch(typeof(Teleport), "Interact")] private static void TeleportInteractPrefix(Teleport __instance, Humanoid character, out Entrances.Entry __state) { __state = Entrances.Before(__instance, character); } [HarmonyPostfix] [HarmonyPatch(typeof(Teleport), "Interact")] private static void TeleportInteractPostfix(bool __result, Entrances.Entry __state) { Entrances.After(__state, __result); } [HarmonyPostfix] [HarmonyPatch(typeof(TeleportWorld), "UpdatePortal")] private static void UpdatePortal(TeleportWorld __instance) { Portals.Tick(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(TeleportWorld), "GetHoverText")] private static void PortalHoverText(TeleportWorld __instance, ref string __result) { try { if (!string.IsNullOrEmpty(__result)) { __result += Hiding.HoverLine(__instance); } } catch (Exception ex) { VardaPlugin.Log.LogWarning((object)("Could not add the hide line to a portal's hover text (" + ex.GetType().Name + ": " + ex.Message + ").")); } } [HarmonyPostfix] [HarmonyPatch(typeof(Terminal), "InitTerminal")] private static void InitTerminal() { DevConsole.Register(); } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "Awake")] private static void MinimapAwake() { Icons.Reset(); IconDump.Reset(); } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "OnSpawned")] private static void OnSpawned(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && VardaConfig.Enabled.Value) { Icons.Warm(); IconDump.Run(); Remembered.Load(); Remembered.Apply(); Portals.Watch(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Minimap), "SaveMapData")] private static void SaveMapData() { Remembered.MapTaken(); } [HarmonyPostfix] [HarmonyPatch(typeof(Game), "SavePlayerProfile")] private static void SavePlayerProfile() { Remembered.MapWritten(); } } [BepInPlugin("ezomic.valheim.varda", "Varda", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class VardaPlugin : BaseUnityPlugin { public const string PluginGuid = "ezomic.valheim.varda"; public const string PluginName = "Varda"; public const string PluginVersion = "1.0.0"; public const string PluginAuthor = "Robbin Thijssen"; private const string CoreGuid = "ezomic.valheim.core"; internal static ManualLogSource Log; internal static bool CorePresent; private Harmony _harmony; private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; VardaConfig.Bind(((BaseUnityPlugin)this).Config); TryRegisterWithCore(); _harmony = new Harmony("ezomic.valheim.varda"); _harmony.PatchAll(typeof(VardaPatches)); Log.LogInfo((object)"Varda 1.0.0 by Robbin Thijssen - ready."); } private void TryRegisterWithCore() { CorePresent = Chainloader.PluginInfos.ContainsKey("ezomic.valheim.core"); if (!CorePresent) { Log.LogInfo((object)"Core not installed - running standalone, without the version gate."); } else { RegisterWithCore(); } } [MethodImpl(MethodImplOptions.NoInlining)] private void RegisterWithCore() { Suite.Register("ezomic.valheim.varda", "Varda", "1.0.0", ((BaseUnityPlugin)this).Config, (Requirement)1, (Assembly)null); Suite.Local((ConfigEntryBase[])(object)new ConfigEntryBase[14] { (ConfigEntryBase)VardaConfig.Enabled, (ConfigEntryBase)VardaConfig.Dungeons, (ConfigEntryBase)VardaConfig.Portals, (ConfigEntryBase)VardaConfig.RemoveDestroyedPortals, (ConfigEntryBase)VardaConfig.HidePortalKey, (ConfigEntryBase)VardaConfig.NameDungeons, (ConfigEntryBase)VardaConfig.DungeonPinType, (ConfigEntryBase)VardaConfig.PortalPinType, (ConfigEntryBase)VardaConfig.DungeonIcon, (ConfigEntryBase)VardaConfig.PortalIcon, (ConfigEntryBase)VardaConfig.MergeRadius, (ConfigEntryBase)VardaConfig.PortalMergeRadius, (ConfigEntryBase)VardaConfig.DumpIcons, (ConfigEntryBase)VardaConfig.Verbose }); } private void Update() { Portals.Sweep(); Hiding.Listen(); } private void OnDestroy() { if (_harmony != null) { _harmony.UnpatchSelf(); } } } }