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 Auto Mapping v1.1.4
QuietMap.dll
Decompiled 13 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Splatform; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.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 OctoberJemini.QuietMap { [BepInPlugin("OctoberJemini.QuietMap", "Auto Mapping", "1.1.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(Minimap), "UpdateExplore")] private static class ExplorationScopePatch { private static void Prefix(Player __1) { if ((Object)(object)Instance != (Object)null) { Instance.localExploration = Object.op_Implicit((Object)(object)__1) && (Object)(object)__1 == (Object)(object)Player.m_localPlayer; } } private static void Finalizer() { if ((Object)(object)Instance != (Object)null) { Instance.localExploration = false; } } } [HarmonyPatch(typeof(Minimap), "Explore", new Type[] { typeof(Vector3), typeof(float) })] private static class ExplorationRadiusPatch { private static void Postfix(float __1) { Plugin instance = Instance; if ((Object)(object)instance != (Object)null && instance.localExploration && __1 > 0f && !float.IsNaN(__1) && !float.IsInfinity(__1)) { instance.effectiveRadius = __1; } } } private sealed class Pin { public PinData Data; public List<string> Keys; public string Kind; public bool Borrowed; } [HarmonyPatch(typeof(ZDOMan), "HandleDestroyedZDO")] private static class PortalDestroyedPatch { private static void Postfix(ZDOID __0) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) Plugin instance = Instance; if ((Object)(object)instance == (Object)null || !instance.ready || instance.loadFailed || instance.session == null) { return; } try { if ((ZDOMan.instance == null || ZDOMan.instance.GetZDO(__0) == null) && instance.records.TryGetValue(Key(__0), out var value) && !(value.Kind != "Portal")) { value.Available = false; instance.missing.Remove(value.Key); instance.dirty = true; if (Object.op_Implicit((Object)(object)instance.map) && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { instance.Render(((Component)Player.m_localPlayer).transform.position); } instance.Save(); } } catch (Exception e) { instance.Warn("destroyed portal marker", e); } } } [HarmonyPatch(typeof(TeleportWorld), "Interact")] private static class PortalInteractPatch { private static void Postfix(TeleportWorld __instance, Humanoid __0, bool __1) { if (!__1) { Instance?.PortalInteraction(__instance, __0); } } } [HarmonyPatch(typeof(TeleportWorld), "Teleport")] private static class PortalUsePatch { private static void Prefix(TeleportWorld __instance, Player __0) { Instance?.PortalInteraction(__instance, (Humanoid)(object)__0); } } [HarmonyPatch(typeof(TeleportWorld), "SetText")] private static class PortalRenamePatch { private static void Postfix(TeleportWorld __instance) { Instance?.PortalInteraction(__instance, (Humanoid)(object)Player.m_localPlayer); } } [HarmonyPatch(typeof(Teleport), "Interact")] private static class DungeonEntryPatch { private static void Postfix(Teleport __instance, Humanoid __0, bool __result) { Instance?.EnterDungeon(__instance, __0, __result); } } [HarmonyPatch(typeof(Minimap), "UpdatePins")] private static class StylePatch { private static void Postfix() { if ((Object)(object)Instance != (Object)null && Instance.ready) { Instance.Style(); } } } [HarmonyPatch(typeof(Minimap), "RemovePin", new Type[] { typeof(PinData) })] private static class RemovePatch { private static void Prefix(PinData __0) { Plugin instance = Instance; if ((Object)(object)instance == (Object)null || instance.internalRemove) { return; } Pin pin = instance.pins.Values.FirstOrDefault((Pin p) => p.Data == __0); if (pin == null || pin.Borrowed) { return; } foreach (string key in pin.Keys) { if (instance.records.TryGetValue(key, out var value)) { value.Deleted = true; instance.dirty = true; } } } } [HarmonyPatch(typeof(Minimap), "SaveMapData")] private static class SavePatch { private static void Prefix() { Instance?.Save(); } } public const string Guid = "OctoberJemini.QuietMap"; internal static Plugin Instance; private ConfigEntry<bool> enabledSetting; private ConfigEntry<bool> dungeons; private ConfigEntry<bool> portals; private ConfigEntry<bool> markVisited; private ConfigEntry<float> portalScale; private ConfigEntry<float> landmarkScale; private ConfigEntry<float> visitedOpacity; private ConfigEntry<string> extraDungeons; private readonly Dictionary<string, Record> records = new Dictionary<string, Record>(); private readonly Dictionary<string, Pin> pins = new Dictionary<string, Pin>(); private readonly Dictionary<string, int> missing = new Dictionary<string, int>(); private readonly HashSet<string> warned = new HashSet<string>(); private readonly HashSet<string> insideLocations = new HashSet<string>(); private static readonly FieldInfo Instances = AccessTools.Field(typeof(ZNetScene), "m_instances"); private static readonly FieldInfo Locations = AccessTools.Field(typeof(Location), "s_allLocations"); private static readonly FieldInfo GamePins = AccessTools.Field(typeof(Minimap), "m_pins"); private static readonly FieldInfo LocationPins = AccessTools.Field(typeof(Minimap), "m_locationPins"); private readonly HashSet<PinData> vendorPins = new HashSet<PinData>(); private readonly Dictionary<Transform, Vector3> nativeScales = new Dictionary<Transform, Vector3>(); private float nextLandmarkCheck; private static readonly MethodInfo MapData = AccessTools.Method(typeof(Minimap), "GetMapData", (Type[])null, (Type[])null); private Harmony harmony; private string session; private string path; private Minimap map; private float nextTick; private float nextSave; private float effectiveRadius; private bool localExploration; private bool dirty; private bool internalRemove; private bool ready; private bool loadFailed; private float DiscoveryRadius { get { if (!(effectiveRadius > 0f)) { if (!Object.op_Implicit((Object)(object)map)) { return 0f; } return map.m_exploreRadius; } return effectiveRadius; } } private static bool WithinDiscovery(Vector3 point, Vector3 player, float distance) { //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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_0024: Unknown result type (might be due to invalid IL or missing references) if (Character.InInterior(point) != Character.InInterior(player)) { return false; } float num = point.x - player.x; float num2 = point.z - player.z; if (distance > 0f) { return num * num + num2 * num2 <= distance * distance; } return false; } public void Awake() { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown Instance = this; enabledSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Automatically maintain discovered map markers. No other map mod is required."); dungeons = ((BaseUnityPlugin)this).Config.Bind<bool>("Tracking", "Dungeons", true, "Pin encountered dungeons, outdoor landmarks and More World Locations POIs. No resource scans."); portals = ((BaseUnityPlugin)this).Config.Bind<bool>("Tracking", "Portals", true, "Automatically pin placed or discovered portals, update their tag, and remove destroyed portals."); markVisited = ((BaseUnityPlugin)this).Config.Bind<bool>("Tracking", "Cross off visited locations", true, "Apply the normal map X when entering a dungeon or outdoor landmark. Visited, not fully looted. Portals, bosses, traders and ports are not auto-crossed."); visitedOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "Visited pin opacity", 0.4f, new ConfigDescription("Opacity of crossed-out location icons and labels; the X stays visible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>())); portalScale = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "Portal icon scale", 0.85f, new ConfigDescription("Size of the game's familiar portal symbol.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.4f, 1.5f), Array.Empty<object>())); landmarkScale = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "Boss and vendor icon scale", 1f, new ConfigDescription("Final icon size relative to a standard map pin, compensating for oversized vanilla markers. Default is slightly larger than Quiet Map's 0.85 portal icons. Artwork and pin labels are preserved.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 1.5f), Array.Empty<object>())); extraDungeons = ((BaseUnityPlugin)this).Config.Bind<string>("Additional objects", "Dungeon prefabs", "", "Comma-separated location prefab names to recognize as dungeons."); string[] array = new string[3] { "digi.valheim.automappins", "com.noodle.autopoi", "com.oathorse.DWMP" }; foreach (string text in array) { if (Chainloader.PluginInfos.ContainsKey(text)) { ((BaseUnityPlugin)this).Logger.LogError((object)("Quiet Map inactive to prevent duplicate pins. Disable " + text + " and restart.")); return; } } try { if (Instances == null || Locations == null || GamePins == null) { throw new MissingMemberException("Game map/object tracking API changed"); } harmony = new Harmony("OctoberJemini.QuietMap"); harmony.PatchAll(typeof(Plugin).Assembly); ready = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Auto Mapping landmark mode ready. No chest, ore, pickup or dungeon-loot scanning."); } catch (Exception ex) { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } ((BaseUnityPlugin)this).Logger.LogError((object)("Quiet Map inactive: " + ex)); } } private static string Clean(string name) { return (name ?? "").Replace("(Clone)", "").Trim(); } private static string Key(ZDOID id) { return "z:" + ((ZDOID)(ref id)).UserID.ToString(CultureInfo.InvariantCulture) + ":" + ((ZDOID)(ref id)).ID.ToString(CultureInfo.InvariantCulture); } private static Vector3 Position(Record r) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(r.X, r.Y, r.Z); } private static bool Extra(ConfigEntry<string> entry, string name) { return entry.Value.Split(',').Any((string s) => string.Equals(s.Trim(), name, StringComparison.OrdinalIgnoreCase)); } private static string Display(string raw) { if (string.IsNullOrEmpty(raw)) { return "Unknown"; } string text = ((Localization.instance != null) ? Localization.instance.Localize(raw) : raw); if (!text.StartsWith("$")) { return text; } return Regex.Replace(text.TrimStart('$').Replace("piece_", "").Replace("item_", "") .Replace('_', ' '), "([a-z])([A-Z])", "$1 $2"); } private static string Readable(string raw) { return Regex.Replace(Clean(raw).Replace('_', ' '), "([a-z])([A-Z])", "$1 $2"); } private static string DungeonName(string raw) { string text = raw.ToLowerInvariant(); if (text.StartsWith("sunkencrypt")) { return "Sunken Crypt"; } if (text.StartsWith("crypt")) { return "Burial Chambers"; } if (text.StartsWith("trollcave")) { return "Troll Cave"; } if (text.StartsWith("mountaincave")) { return "Frost Cave"; } if (text.Contains("dvergrtownentrance")) { return "Infested Mine"; } if (text.StartsWith("hildir_crypt")) { return "Smouldering Tomb"; } if (text.StartsWith("hildir_cave")) { return "Howling Cavern"; } if (text.StartsWith("hildir_plainsfortress")) { return "Sealed Tower"; } if (text.StartsWith("morgenhole")) { return "Putrid Hole"; } if (text.StartsWith("morkborg") || text.Contains("morkhalla")) { return "Mörkhalla"; } if (text.StartsWith("thehole") || text.StartsWith("the_hole")) { return "Winding Tunnels"; } if (text.StartsWith("bearcave")) { return "Bear Cave"; } return Readable(raw); } private void Update() { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) if (!ready) { return; } try { Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)Minimap.instance) || !Object.op_Implicit((Object)(object)ZNet.instance)) { if (session != null) { EndSession(); } return; } string text = ZNet.instance.GetWorldUID().ToString(CultureInfo.InvariantCulture) + "-" + localPlayer.GetPlayerID().ToString(CultureInfo.InvariantCulture); if (session != text || (Object)(object)map != (Object)(object)Minimap.instance) { EndSession(); StartSession(text); } if (!loadFailed && !(Time.unscaledTime < nextTick)) { nextTick = Time.unscaledTime + 2f; if (enabledSetting.Value) { Scan(((Component)localPlayer).transform.position); Render(((Component)localPlayer).transform.position); } else { ClearPins(); } if (Time.unscaledTime >= nextSave) { nextSave = Time.unscaledTime + 10f; Save(); } } } catch (Exception e) { Warn("tick", e); } } private void StartSession(string key) { session = key; map = Minimap.instance; path = Path.Combine(Paths.ConfigPath, "QuietMap", key + ".json"); loadFailed = false; if (File.Exists(path)) { try { SaveData saveData = JsonConvert.DeserializeObject<SaveData>(File.ReadAllText(path)); if (saveData == null || saveData.Version != 1) { throw new InvalidDataException("Unsupported or empty map save"); } foreach (Record record2 in saveData.Records) { if (record2 != null && !string.IsNullOrEmpty(record2.Key)) { records[record2.Key] = record2; } } } catch (Exception e) { loadFailed = true; Warn("load", e); return; } } else { ImportPriorDiscoveries(); } Record[] array = records.Values.ToArray(); foreach (Record record in array) { if (!LandmarkPolicy.KeepRecord(record.Kind)) { records.Remove(record.Key); dirty = true; } else if (record.Kind != "Portal" && !string.IsNullOrEmpty(record.CompletionReason)) { record.Available = true; record.Visited = true; record.CompletionReason = null; dirty = true; } } Save(); nextTick = 0f; nextSave = Time.unscaledTime + 10f; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Quiet Map loaded " + records.Count + " known markers for world/character " + key)); } private static string FileKey(string value) { return new string((value ?? "").Select((char c) => (!char.IsLetterOrDigit(c) && c != '_' && c != '-') ? '_' : c).ToArray()); } private void ImportPriorDiscoveries() { try { PlayerProfile val = (Object.op_Implicit((Object)(object)Game.instance) ? Game.instance.GetPlayerProfile() : null); if (val == null) { return; } string text = Path.Combine(Paths.ConfigPath, "DigiAutoMapPins", FileKey(ZNet.instance.GetWorldName()) + "-" + ZNet.instance.GetWorldUID() + "." + FileKey(val.GetFilename()) + ".txt"); if (!File.Exists(text)) { return; } string[] array = File.ReadAllLines(text); for (int i = 0; i < array.Length; i++) { Record record = Migration.Read(array[i]); if (record != null) { if (record.Kind == "Dungeon") { record.Name = DungeonName(record.Prefab); } records[record.Key] = record; dirty = true; } } Save(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Imported " + records.Count + " known portal/dungeon markers from this character's former map tracker; original file retained.")); } catch (Exception e) { Warn("prior map import", e); } } private void EndSession() { effectiveRadius = 0f; localExploration = false; Save(); ClearPins(); RestoreNativeSizes(); vendorPins.Clear(); nextLandmarkCheck = 0f; records.Clear(); missing.Clear(); insideLocations.Clear(); session = null; path = null; map = null; dirty = false; loadFailed = false; } private void Save() { if (!dirty || path == null || loadFailed) { return; } try { Directory.CreateDirectory(Path.GetDirectoryName(path)); string sourceFileName = path + ".tmp"; File.WriteAllText(sourceFileName, JsonConvert.SerializeObject((object)new SaveData { Records = records.Values.ToList() }, (Formatting)1)); if (File.Exists(path)) { File.Replace(sourceFileName, path, path + ".bak"); } else { File.Move(sourceFileName, path); } dirty = false; } catch (Exception e) { Warn("save", e); } } private void Warn(string context, Exception e) { if (warned.Add(context)) { ((BaseUnityPlugin)this).Logger.LogError((object)("Quiet Map " + context + ": " + e)); } } private void Observe(string key, string kind, string name, string prefab, Vector3 pos, bool available, ZDO zdo = null) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if (!records.TryGetValue(key, out var value)) { Record record = records.Values.FirstOrDefault(delegate(Record p) { //IL_0027: 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_0032: 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) if (p.Key.StartsWith("legacy:", StringComparison.Ordinal) && p.Kind == kind) { Vector3 val2 = Position(p) - pos; return ((Vector3)(ref val2)).sqrMagnitude < 4f; } return false; }); if (record != null) { records.Remove(record.Key); record.Key = key; value = record; records[key] = value; if (zdo != null) { value.User = ((ZDOID)(ref zdo.m_uid)).UserID; value.Id = ((ZDOID)(ref zdo.m_uid)).ID; } dirty = true; } } if (value == null) { value = new Record { Key = key, Kind = kind, Name = name, Prefab = prefab, X = pos.x, Y = pos.y, Z = pos.z }; if (zdo != null) { value.User = ((ZDOID)(ref zdo.m_uid)).UserID; value.Id = ((ZDOID)(ref zdo.m_uid)).ID; } records.Add(key, value); dirty = true; } if (value.Available == available && !(value.Name != name)) { Vector3 val = Position(value) - pos; if (!(((Vector3)(ref val)).sqrMagnitude > 0.01f)) { goto IL_01ba; } } value.Available = available; value.Name = name; value.X = pos.x; value.Y = pos.y; value.Z = pos.z; dirty = true; goto IL_01ba; IL_01ba: missing.Remove(key); } private void Scan(Vector3 player) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0125: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) ZNetScene instance = ZNetScene.instance; if (!Object.op_Implicit((Object)(object)instance) || !(Instances.GetValue(instance) is Dictionary<ZDO, ZNetView> source)) { return; } if (portals.Value) { KeyValuePair<ZDO, ZNetView>[] array = source.ToArray(); foreach (KeyValuePair<ZDO, ZNetView> keyValuePair in array) { ZNetView value = keyValuePair.Value; if (Object.op_Implicit((Object)(object)value) && value.IsValid() && WithinDiscovery(((Component)value).transform.position, player, DiscoveryRadius)) { TeleportWorld component = ((Component)value).GetComponent<TeleportWorld>(); if (Object.op_Implicit((Object)(object)component)) { TrackPortal(component, interacted: false); } } } } ScanLocations(player); Record[] array2 = records.Values.Where((Record r) => r.Kind == "Portal" && r.Id != 0 && r.Available).ToArray(); foreach (Record record in array2) { Vector3 val = Position(record) - player; bool flag = ((Vector3)(ref val)).sqrMagnitude < 1600f; if (flag && Object.op_Implicit((Object)(object)ZoneSystem.instance) && ZoneSystem.instance.IsZoneLoaded(Position(record))) { ZDOMan instance2 = ZDOMan.instance; ZDO val2 = ((instance2 != null) ? instance2.GetZDO(new ZDOID(record.User, record.Id)) : null); int num; if (val2 != null && (record.Prefab == "portal" || val2.GetPrefab() == StringExtensionMethods.GetStableHashCode(record.Prefab))) { val = val2.GetPosition() - Position(record); num = ((((Vector3)(ref val)).sqrMagnitude < 4f) ? 1 : 0); } else { num = 0; } bool flag2 = (byte)num != 0; int value2; int num2 = ((!flag2) ? ((!missing.TryGetValue(record.Key, out value2)) ? 1 : (value2 + 1)) : 0); missing[record.Key] = num2; if (Policy.MissingMeansDestroyed(flag, zoneLoaded: true, flag2, num2)) { record.Available = false; dirty = true; } } } } private void TrackPortal(TeleportWorld portal, bool interacted) { //IL_005b: 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_0132: Unknown result type (might be due to invalid IL or missing references) if (!ready || loadFailed || session == null || !enabledSetting.Value || !portals.Value || !Object.op_Implicit((Object)(object)portal)) { return; } ZNetView component = ((Component)portal).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid()) { return; } ZDO zDO = component.GetZDO(); string key = Key(zDO.m_uid); string text = Clean(((Object)((Component)component).gameObject).name); string text2 = zDO.GetString(ZDOVars.s_tag, ""); Observe(key, "Portal", string.IsNullOrWhiteSpace(text2) ? "Portal" : text2, text, ((Component)component).transform.position, available: true, zDO); Record record = records[key]; if (Policy.RestorePortal(record, interacted)) { record.Deleted = false; dirty = true; } if (record.Prefab != text) { record.Prefab = text; dirty = true; } if (interacted) { nextTick = 0f; Save(); if (Object.op_Implicit((Object)(object)map) && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { Render(((Component)Player.m_localPlayer).transform.position); } } } private void PortalInteraction(TeleportWorld portal, Humanoid user) { if (!Object.op_Implicit((Object)(object)user) || (Object)(object)user != (Object)(object)Player.m_localPlayer) { return; } try { TrackPortal(portal, interacted: true); } catch (Exception e) { Warn("portal interaction", e); } } private string LocationName(string name) { if (LandmarkPolicy.Aio.TryGetValue(name ?? "", out var value)) { return value.Name; } string text; if (!Policy.IsDungeonName(name)) { text = LandmarkPolicy.OutdoorName(name); if (text == null) { return DungeonName(name); } } else { text = DungeonName(name); } return text; } private bool Recognized(string name) { if (!LandmarkPolicy.Aio.ContainsKey(name ?? "") && LandmarkPolicy.OutdoorName(name) == null && !Policy.IsDungeonName(name)) { return Extra(extraDungeons, name); } return true; } private Record ObserveLandmark(string name, Vector3 pos) { //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_00a5: Unknown result type (might be due to invalid IL or missing references) Record record = records.Values.FirstOrDefault(delegate(Record r) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //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) if (r.Kind != "Portal") { Vector3 val = Position(r) - pos; return ((Vector3)(ref val)).sqrMagnitude < 100f; } return false; }); if (record != null) { string text = LocationName(name); if (record.Name != text) { record.Name = text; dirty = true; } return record; } string key = "place:" + Mathf.RoundToInt(pos.x) + ":" + Mathf.RoundToInt(pos.z); Observe(key, "Landmark", LocationName(name), name, pos, available: true); return records[key]; } private void SetVisited(Record record) { if (!markVisited.Value || record == null || LandmarkPolicy.IsService(record.Prefab)) { return; } if (!record.Visited) { record.Visited = true; dirty = true; } foreach (Pin value in pins.Values) { if (value.Keys.Contains(record.Key)) { value.Data.m_checked = true; } } } private void ScanLocations(Vector3 player) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_022d: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) if (!dungeons.Value || !Object.op_Implicit((Object)(object)ZoneSystem.instance)) { insideLocations.Clear(); return; } bool flag = Character.InInterior(player); Location val = (flag ? Location.GetLocation(player, true) : null); List<Location> list = Locations.GetValue(null) as List<Location>; HashSet<string> hashSet = new HashSet<string>(); foreach (LocationInstance location in ZoneSystem.instance.GetLocationList()) { if (!location.m_placed || location.m_location == null) { continue; } string prefabName = location.m_location.m_prefabName; if (!Recognized(prefabName)) { continue; } Vector3 pos = location.m_position; int num; if (Object.op_Implicit((Object)(object)val)) { Vector3 val2 = ((Component)val).transform.position - pos; num = ((((Vector3)(ref val2)).sqrMagnitude < 100f) ? 1 : 0); } else { num = 0; } bool flag2 = (byte)num != 0; if (!flag2 && !WithinDiscovery(pos, player, DiscoveryRadius)) { continue; } Record record = ObserveLandmark(prefabName, pos); Location val3 = list?.FirstOrDefault((Func<Location, bool>)delegate(Location l) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)l)) { Vector3 val4 = ((Component)l).transform.position - pos; return ((Vector3)(ref val4)).sqrMagnitude < 100f; } return false; }); bool interiorLocation = (Object.op_Implicit((Object)(object)val3) ? val3.m_hasInterior : (location.m_location.m_interiorRadius > 0f)); float num2 = player.x - pos.x; float num3 = player.z - pos.z; float radius = LandmarkPolicy.EnterRadius(location.m_location.m_exteriorRadius); if (LandmarkPolicy.Entered(interiorLocation, flag, flag2, num2 * num2 + num3 * num3, radius, player.y - pos.y)) { hashSet.Add(record.Key); if (!insideLocations.Contains(record.Key)) { SetVisited(record); } } } if (Object.op_Implicit((Object)(object)val) && val.m_hasInterior) { Record record2 = ObserveLandmark(Clean(((Object)((Component)val).gameObject).name), ((Component)val).transform.position); hashSet.Add(record2.Key); if (!insideLocations.Contains(record2.Key)) { SetVisited(record2); } } insideLocations.Clear(); foreach (string item in hashSet) { insideLocations.Add(item); } } private void EnterDungeon(Teleport entrance, Humanoid user, bool succeeded) { //IL_006b: 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_0096: 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) if (!ready || !enabledSetting.Value || !dungeons.Value || !markVisited.Value || session == null || loadFailed || !succeeded || (Object)(object)user != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)entrance) || !Object.op_Implicit((Object)(object)entrance.m_targetPoint) || Character.InInterior(((Component)entrance).transform.position) || !Character.InInterior(((Component)entrance.m_targetPoint).transform.position)) { return; } try { Location location = Location.GetLocation(((Component)entrance).transform.position, true); if (Object.op_Implicit((Object)(object)location) && location.m_hasInterior) { SetVisited(ObserveLandmark(Clean(((Object)((Component)location).gameObject).name), ((Component)location).transform.position)); Save(); } } catch (Exception e) { Warn("dungeon entry", e); } } private bool CategoryOn(string kind) { switch (kind) { case "Dungeon": case "Landmark": return dungeons.Value; default: return false; case "Portal": return portals.Value; } } private void Render(Vector3 player) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_013e: 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_0462: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)map)) { return; } Dictionary<string, List<Record>> dictionary = ResourceGrouping.Build(records.Values.Where((Record r) => CategoryOn(r.Kind) && Policy.Show(r.Kind, r.Available, r.Deleted, r.Y > 3000f, player.y > 3000f))); string[] array = pins.Keys.ToArray(); foreach (string key in array) { if (!dictionary.ContainsKey(key)) { RemovePin(key); } } List<PinData> list = GamePins.GetValue(map) as List<PinData>; foreach (KeyValuePair<string, List<Record>> item in dictionary) { List<Record> value = item.Value; Record first = value[0]; Vector3 pos = new Vector3(value.Average((Record r) => r.X), value.Average((Record r) => r.Y), value.Average((Record r) => r.Z)); string label = first.Name; if (pins.TryGetValue(item.Key, out var value2) && value2.Borrowed && list != null && !list.Contains(value2.Data)) { RemovePin(item.Key); } if (!pins.TryGetValue(item.Key, out var value3)) { Dictionary<Vector3, PinData> dictionary2 = LocationPins?.GetValue(map) as Dictionary<Vector3, PinData>; PinData val = ((first.Kind != "Portal" && dictionary2 != null) ? ((IEnumerable<PinData>)dictionary2.Values).FirstOrDefault((Func<PinData, bool>)delegate(PinData p) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_000b: 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) //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) if ((int)p.m_type != 9) { Vector3 val4 = p.m_pos - pos; return ((Vector3)(ref val4)).sqrMagnitude < 100f; } return false; }) : null); if (first.Kind != "Portal" && val == null && list != null) { val = ((IEnumerable<PinData>)list).FirstOrDefault((Func<PinData, bool>)delegate(PinData p) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //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) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (p.m_save && (int)p.m_type != 9 && (int)p.m_type != 6) { Vector3 val4 = p.m_pos - pos; if (((Vector3)(ref val4)).sqrMagnitude < 225f) { return LandmarkPolicy.MatchingSavedPin(p.m_name, label, first.Prefab); } } return false; }); } if (first.Kind != "Portal" && val == null && list != null && list.Any(delegate(PinData p) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (p.m_save) { Vector3 val4 = p.m_pos - pos; return ((Vector3)(ref val4)).sqrMagnitude < 225f; } return false; })) { continue; } PinData val2 = ((first.Kind == "Portal" && list != null) ? ((IEnumerable<PinData>)list).FirstOrDefault((Func<PinData, bool>)delegate(PinData p) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0022: Unknown result type (might be due to invalid IL or missing references) if (p.m_save && (int)p.m_type == 6) { Vector3 val4 = p.m_pos - pos; if (((Vector3)(ref val4)).sqrMagnitude < 4f) { return p.m_name == label; } } return false; }) : null); PinType val3 = (PinType)((first.Kind == "Portal") ? 6 : 3); if (val2 != null) { if (!BackupMap()) { continue; } Save(); if (dirty) { continue; } val2.m_save = false; } value3 = new Pin { Borrowed = (val != null), Data = (val ?? val2 ?? map.AddPin(pos, val3, label, false, first.Visited, 0L, default(PlatformUserID))), Keys = value.Select((Record r) => r.Key).ToList(), Kind = first.Kind }; pins.Add(item.Key, value3); if (val != null) { if (val.m_checked && !first.Visited) { first.Visited = true; dirty = true; } value3.Data.m_checked = first.Visited; } continue; } value3.Keys = value.Select((Record r) => r.Key).ToList(); if (!value3.Borrowed && value3.Data.m_name != label) { RemovePin(item.Key); continue; } if (!value3.Borrowed) { value3.Data.m_pos = pos; } value3.Data.m_checked = first.Visited; } } private bool BackupMap() { try { string text = path + ".native-map-before-portals.bin"; if (File.Exists(text)) { return true; } if (MapData == null) { return false; } Directory.CreateDirectory(Path.GetDirectoryName(text)); File.WriteAllBytes(text, (byte[])MapData.Invoke(map, null)); return true; } catch (Exception e) { Warn("portal migration backup", e); return false; } } private void RemovePin(string key) { //IL_0036: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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) if (!pins.TryGetValue(key, out var value)) { return; } if (value.Borrowed) { if (Object.op_Implicit((Object)(object)value.Data.m_iconElement)) { Color color = ((Graphic)value.Data.m_iconElement).color; color.a = 1f; ((Graphic)value.Data.m_iconElement).color = color; } PinNameData namePinData = value.Data.m_NamePinData; TMP_Text val = ((namePinData != null) ? namePinData.PinNameText : null); if (Object.op_Implicit((Object)(object)val)) { Color color2 = ((Graphic)val).color; color2.a = 1f; ((Graphic)val).color = color2; } } internalRemove = true; try { if (Object.op_Implicit((Object)(object)map) && !value.Borrowed) { map.RemovePin(value.Data); } } finally { internalRemove = false; pins.Remove(key); } } private void ClearPins() { string[] array = pins.Keys.ToArray(); foreach (string key in array) { RemovePin(key); } } private void Style() { //IL_00a1: 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_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0113: 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_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) if (!enabledSetting.Value) { RestoreNativeSizes(); return; } StyleLandmarks(); foreach (Pin value2 in pins.Values) { float num = ((value2.Kind == "Portal") ? portalScale.Value : (landmarkScale.Value / (value2.Data.m_doubleSize ? 2f : 1f))); if (Object.op_Implicit((Object)(object)value2.Data.m_uiElement)) { ((Transform)value2.Data.m_uiElement).localScale = new Vector3(num, num, 1f); } float a = LandmarkPolicy.Alpha(value2.Data.m_checked && value2.Kind != "Portal", visitedOpacity.Value); if (Object.op_Implicit((Object)(object)value2.Data.m_iconElement)) { Color color = ((Graphic)value2.Data.m_iconElement).color; color.a = a; ((Graphic)value2.Data.m_iconElement).color = color; } PinNameData namePinData = value2.Data.m_NamePinData; TMP_Text val = ((namePinData != null) ? namePinData.PinNameText : null); if (Object.op_Implicit((Object)(object)val)) { val.transform.localScale = Vector3.one; Color color2 = ((Graphic)val).color; color2.a = a; ((Graphic)val).color = color2; } foreach (string key in value2.Keys) { if (records.TryGetValue(key, out var value) && value.Visited != value2.Data.m_checked) { value.Visited = value2.Data.m_checked; dirty = true; } } } } private void StyleLandmarks() { //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Invalid comparison between Unknown and I4 //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)map)) { return; } if (Time.unscaledTime >= nextLandmarkCheck) { nextLandmarkCheck = Time.unscaledTime + 2f; vendorPins.Clear(); Dictionary<Vector3, string> dictionary = new Dictionary<Vector3, string>(); if (Object.op_Implicit((Object)(object)ZoneSystem.instance)) { ZoneSystem.instance.GetLocationIcons(dictionary); } if (LocationPins?.GetValue(map) is Dictionary<Vector3, PinData> dictionary2) { foreach (KeyValuePair<Vector3, PinData> item in dictionary2) { if (dictionary.TryGetValue(item.Key, out var value) && !string.IsNullOrEmpty((value ?? "").ToLowerInvariant())) { vendorPins.Add(item.Value); } } } Type type = AccessTools.TypeByName("More_World_Locations_AIO.PortMap"); IEnumerable enumerable = ((type == null) ? null : (AccessTools.Field(type, "s_entries")?.GetValue(null) as IEnumerable)); if (enumerable != null) { foreach (object item2 in enumerable) { if (item2 != null) { object? obj = AccessTools.Field(item2.GetType(), "Pin")?.GetValue(item2); PinData val = (PinData)((obj is PinData) ? obj : null); if (val != null) { vendorPins.Add(val); } } } } Transform[] array = nativeScales.Keys.Where((Transform t) => !Object.op_Implicit((Object)(object)t)).ToArray(); foreach (Transform key in array) { nativeScales.Remove(key); } } if (!(GamePins.GetValue(map) is List<PinData> list)) { return; } foreach (PinData item3 in list) { if (((int)item3.m_type == 9 || vendorPins.Contains(item3)) && Object.op_Implicit((Object)(object)item3.m_uiElement) && !(item3.m_worldSize > 0f)) { Transform uiElement = (Transform)(object)item3.m_uiElement; if (!nativeScales.ContainsKey(uiElement)) { nativeScales.Add(uiElement, uiElement.localScale); } float num2 = landmarkScale.Value / (item3.m_doubleSize ? 2f : 1f); uiElement.localScale = new Vector3(num2, num2, 1f); } } } private void RestoreNativeSizes() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<Transform, Vector3> nativeScale in nativeScales) { if (Object.op_Implicit((Object)(object)nativeScale.Key)) { nativeScale.Key.localScale = nativeScale.Value; } } nativeScales.Clear(); } private void OnDestroy() { EndSession(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } internal static class Policy { private static readonly HashSet<string> Valuable = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "SurtlingCore", "BlackCore", "MoltenCore", "FrostCore", "RoyalJelly", "GoblinTotem", "DragonEgg", "VoltureEgg", "Tar", "SulfurStone", "WolfHairBundle", "Crystal", "IronOre", "TinOre", "CopperOre", "SilverOre", "Obsidian", "DyrnwynHiltFragment", "DyrnwynBladeFragment", "DyrnwynTipFragment", "GemstoneBlue", "GemstoneGreen", "GemstoneRed", "AncientGemstoneBlack", "AncientGemstoneGreen", "AncientGemstoneOrange", "AncientGemstonePurple" }; private static readonly HashSet<string> Minerals = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "CopperOre", "TinOre", "SilverOre", "IronScrap", "IronOre", "Iron", "CopperScrap", "Obsidian", "FlametalOre", "FlametalOreNew", "BlackMarble", "Softtissue", "Guck", "Chitin", "ProustitePowder", "BellFragment", "GoldOre", "GoldNugget" }; internal static bool IsValuable(string name) { if (name != null) { if (!Valuable.Contains(name)) { return string.Equals(name, "DvergrNeedle", StringComparison.OrdinalIgnoreCase); } return true; } return false; } internal static bool IsMineral(string name) { if (name != null) { return Minerals.Contains(name); } return false; } internal static bool IsCompletionLoot(string name) { if (!IsValuable(name) && !IsMineral(name)) { switch (name) { default: return name == "SilverNecklace"; case "Coins": case "Amber": case "AmberPearl": case "Ruby": break; } } return true; } internal static bool IsGeneratedPoi(string name) { if (!string.IsNullOrEmpty(name)) { if (!name.StartsWith("MWL_", StringComparison.OrdinalIgnoreCase)) { return name.Equals("BFD_Exterior", StringComparison.OrdinalIgnoreCase); } return true; } return false; } internal static bool HideResourceInPoi(string kind, bool inside) { if (inside) { if (!(kind == "Loot")) { return kind == "Ore"; } return true; } return false; } internal static bool DepositPrefab(string name) { string text = (name ?? "").ToLowerInvariant(); if (!text.StartsWith("mudpile") && !text.StartsWith("mineable") && !text.StartsWith("rock") && !text.StartsWith("guck") && !text.StartsWith("giant_brain") && !text.StartsWith("giant_helmet")) { return text.StartsWith("giant_sword"); } return true; } internal static bool LootCrate(string name) { if (!string.Equals(name, "piece_dvergr_crate", StringComparison.OrdinalIgnoreCase)) { return string.Equals(name, "dvergrprops_crate", StringComparison.OrdinalIgnoreCase); } return true; } internal static bool RestorePortal(Record r, bool interacted) { if (r.Kind == "Portal" && r.Deleted) { if (!interacted) { return r.Prefab == "portal"; } return true; } return false; } internal static bool IsTar(Record r) { if (r.Kind == "Loot") { if (!string.Equals(r.Name, "Tar", StringComparison.OrdinalIgnoreCase) && !string.Equals(r.Prefab, "Pickable_Tar", StringComparison.OrdinalIgnoreCase) && !string.Equals(r.Prefab, "Pickable_TarBig", StringComparison.OrdinalIgnoreCase)) { return string.Equals(r.Prefab, "Tar", StringComparison.OrdinalIgnoreCase); } return true; } return false; } internal static bool Small(string kind) { if (!(kind == "Ore") && !(kind == "Chest")) { return kind == "Loot"; } return true; } internal static bool Show(string kind, bool available, bool deleted, bool interior, bool playerInterior) { if (available && !deleted) { if (!(!interior || playerInterior)) { return kind == "Portal"; } return true; } return false; } internal static bool MissingMeansDestroyed(bool inRange, bool zoneLoaded, bool hasZdo, int misses) { if (inRange && zoneLoaded && !hasZdo) { return misses >= 3; } return false; } internal static bool IsDungeonName(string name) { if (string.IsNullOrEmpty(name)) { return false; } string text = name.ToLowerInvariant(); if (!text.Contains("crypt") && !text.Contains("trollcave") && !text.Contains("mountaincave") && !text.Contains("dvergrtownentrance") && !text.Contains("morgenhole") && !text.Contains("charredfortress") && !text.Contains("morkhalla") && !text.StartsWith("morkborg") && !text.Contains("hildir_cave") && !text.Contains("hildir_plainsfortress") && !text.Contains("tomb") && !text.Contains("dungeon") && !text.Contains("bearcave") && !text.StartsWith("thehole") && !text.StartsWith("the_hole")) { return text.StartsWith("thedarkesthole"); } return true; } } public sealed class Record { public string Key; public string Kind; public string Name; public string Prefab; public long User; public uint Id; public float X; public float Y; public float Z; public bool Available = true; public bool Deleted; public bool Visited; public bool DungeonSurveyed; public string CompletionReason; } public sealed class SaveData { public int Version = 1; public List<Record> Records = new List<Record>(); } internal static class Migration { internal static Record Read(string line) { if (string.IsNullOrEmpty(line) || line.StartsWith("#")) { return null; } string[] array = line.Split('\t'); if (array.Length < 10) { return null; } string text = array[0]; string text2 = ((text == "portal") ? "Portal" : ((text.StartsWith("place:") && Policy.IsDungeonName(text.Substring(6))) ? "Dungeon" : null)); if (text2 == null) { return null; } if (!float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array[4], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { return null; } if (float.IsNaN(result) || float.IsInfinity(result) || float.IsNaN(result2) || float.IsInfinity(result2) || float.IsNaN(result3) || float.IsInfinity(result3)) { return null; } Record record = new Record(); record.Key = "legacy:" + text + ":" + array[2] + ":" + array[4]; record.Kind = text2; record.Name = (string.IsNullOrWhiteSpace(array[8]) ? text2 : array[8]); record.Prefab = (text.StartsWith("place:") ? text.Substring(6) : "portal"); record.X = result; record.Y = result2; record.Z = result3; record.Available = !array[6].Contains("E"); record.Deleted = array[6].Contains("D"); record.Visited = array[6].Contains("C"); return record; } } internal static class LandmarkPolicy { internal sealed class Entry { internal string Name; internal string Category; internal bool Service { get { if (!(Category == "Ports") && !(Category == "Traders")) { return Category == "Trainers"; } return true; } } } internal static readonly Dictionary<string, Entry> Aio = Load(); private static Dictionary<string, Entry> Load() { Dictionary<string, Entry> dictionary = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase); using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("QuietMap.AioLandmarks"); if (stream == null) { throw new InvalidDataException("AIO landmark catalog missing"); } using StreamReader streamReader = new StreamReader(stream); string text; while ((text = streamReader.ReadLine()) != null) { string[] array = text.Split('\t'); if (array.Length == 3) { dictionary.Add(array[1], new Entry { Category = array[0], Name = array[2] }); } } return dictionary; } internal static string OutdoorName(string prefab) { string text = (prefab ?? "").ToLowerInvariant(); if (text.StartsWith("tarpit")) { return "Tar Pit"; } if (text.StartsWith("goblincamp")) { return "Fuling Village"; } if (text.StartsWith("woodvillage") || text.StartsWith("draugrvillage")) { return "Draugr Village"; } if (text.StartsWith("greydwarf_camp")) { return "Greydwarf Nest"; } if (text.StartsWith("firehole")) { return "Surtling Geyser"; } if (text.StartsWith("mistlands_dvergrtown") && !text.Contains("entrance")) { return "Dvergr Settlement"; } if (text.StartsWith("mistlands_guardtower") || text.StartsWith("mistlands_dvergrguardtower")) { return "Dvergr Tower"; } if (text.StartsWith("mistlands_harbour") || text.StartsWith("mistlands_dvergrharbour")) { return "Dvergr Harbour"; } if (text.StartsWith("mistlands_viaduct")) { return "Ruined Aqueduct"; } if (text.StartsWith("shipwreck")) { return "Shipwreck"; } return VanillaName(prefab); } private static string VanillaName(string name) { if (string.IsNullOrEmpty(name)) { return null; } if (name.StartsWith("Mistlands_GuardTower1_ruined_new", StringComparison.OrdinalIgnoreCase)) { return "Guard tower 1 ruined new"; } if (name.StartsWith("Mistlands_GuardTower3_ruined_new", StringComparison.OrdinalIgnoreCase)) { return "Guard tower 3 ruined new"; } if (name.StartsWith("Mistlands_DvergrTownEntrance", StringComparison.OrdinalIgnoreCase)) { return "Infested Mine"; } if (name.StartsWith("Mistlands_GuardTower1_new", StringComparison.OrdinalIgnoreCase)) { return "Guard tower 1 new"; } if (name.StartsWith("Mistlands_GuardTower2_new", StringComparison.OrdinalIgnoreCase)) { return "Guard tower 2 new"; } if (name.StartsWith("Mistlands_GuardTower3_new", StringComparison.OrdinalIgnoreCase)) { return "Guard tower 3 new"; } if (name.StartsWith("Mistlands_Lighthouse1_new", StringComparison.OrdinalIgnoreCase)) { return "Lighthouse 1 new"; } if (name.StartsWith("CharredTowerRuins1_dvergr", StringComparison.OrdinalIgnoreCase)) { return "Charred tower ruins 1 dvergr"; } if (name.StartsWith("StoneTowerRuins07_sunk", StringComparison.OrdinalIgnoreCase)) { return "Stone tower ruins 07 sunk"; } if (name.StartsWith("StoneTowerRuins08_sunk", StringComparison.OrdinalIgnoreCase)) { return "Stone tower ruins 08 sunk"; } if (name.StartsWith("StoneTowerRuins09_sunk", StringComparison.OrdinalIgnoreCase)) { return "Stone tower ruins 09 sunk"; } if (name.StartsWith("StoneTowerRuins10_sunk", StringComparison.OrdinalIgnoreCase)) { return "Stone tower ruins 10 sunk"; } if (name.StartsWith("StoneTowerRuins05_leet", StringComparison.OrdinalIgnoreCase)) { return "Stone tower ruins 05 leet"; } if (name.StartsWith("AncientUpgradeStation", StringComparison.OrdinalIgnoreCase)) { return "Ancient upgrade station"; } if (name.StartsWith("Mistlands_StatueGroup", StringComparison.OrdinalIgnoreCase)) { return "Statue group"; } if (name.StartsWith("Hildir_plainsfortress", StringComparison.OrdinalIgnoreCase)) { return "Sealed Tower"; } if (name.StartsWith("Mistlands_Excavation", StringComparison.OrdinalIgnoreCase)) { return "Dvergr excavation"; } if (name.StartsWith("Mistlands_RoadPost", StringComparison.OrdinalIgnoreCase)) { return "Road post"; } if (name.StartsWith("NorthMemorialPlace", StringComparison.OrdinalIgnoreCase)) { return "North memorial place"; } if (name.StartsWith("StoneHouse1_heath", StringComparison.OrdinalIgnoreCase)) { return "Stone house 1 heath"; } if (name.StartsWith("StoneHouse2_heath", StringComparison.OrdinalIgnoreCase)) { return "Stone house 2 heath"; } if (name.StartsWith("StoneHouse5_heath", StringComparison.OrdinalIgnoreCase)) { return "Stone house 5 heath"; } if (name.StartsWith("AbandonedLogCabin", StringComparison.OrdinalIgnoreCase)) { return "Abandoned log cabin"; } if (name.StartsWith("Mistlands_Harbour", StringComparison.OrdinalIgnoreCase)) { return "Dvergr harbour"; } if (name.StartsWith("Mistlands_Viaduct", StringComparison.OrdinalIgnoreCase)) { return "Viaduct"; } if (name.StartsWith("CharredTowerRuins", StringComparison.OrdinalIgnoreCase)) { return "Charred tower ruins"; } if (name.StartsWith("Mistlands_Statue", StringComparison.OrdinalIgnoreCase)) { return "Statue"; } if (name.StartsWith("StoneTowerRuins", StringComparison.OrdinalIgnoreCase)) { return "Stone tower ruins"; } if (name.StartsWith("CharredFortress", StringComparison.OrdinalIgnoreCase)) { return "Charred Fortress"; } if (name.StartsWith("FrozenShip01_DN", StringComparison.OrdinalIgnoreCase)) { return "Frozen ship 01 dn"; } if (name.StartsWith("FrozenShip02_DN", StringComparison.OrdinalIgnoreCase)) { return "Frozen ship 02 dn"; } if (name.StartsWith("FrozenShip03_DN", StringComparison.OrdinalIgnoreCase)) { return "Frozen ship 03 dn"; } if (name.StartsWith("Greydwarf_camp", StringComparison.OrdinalIgnoreCase)) { return "Greydwarf camp"; } if (name.StartsWith("DrakeLorestone", StringComparison.OrdinalIgnoreCase)) { return "Drake lorestone"; } if (name.StartsWith("PlaceofMystery", StringComparison.OrdinalIgnoreCase)) { return "Place of Mystery"; } if (name.StartsWith("ShipWreck01_DN", StringComparison.OrdinalIgnoreCase)) { return "Ship wreck 01 dn"; } if (name.StartsWith("ShipWreck02_DN", StringComparison.OrdinalIgnoreCase)) { return "Ship wreck 02 dn"; } if (name.StartsWith("MountainGrave", StringComparison.OrdinalIgnoreCase)) { return "Mountain grave"; } if (name.StartsWith("FortressRuins", StringComparison.OrdinalIgnoreCase)) { return "Fortress ruins"; } if (name.StartsWith("MountainWell", StringComparison.OrdinalIgnoreCase)) { return "Mountain well"; } if (name.StartsWith("MountainCave", StringComparison.OrdinalIgnoreCase)) { return "Frost Cave"; } if (name.StartsWith("Hildir_crypt", StringComparison.OrdinalIgnoreCase)) { return "Smouldering Tomb"; } if (name.StartsWith("CharredRuins", StringComparison.OrdinalIgnoreCase)) { return "Charred ruins"; } if (name.StartsWith("AshlandRuins", StringComparison.OrdinalIgnoreCase)) { return "Ashland ruins"; } if (name.StartsWith("NorthVillage", StringComparison.OrdinalIgnoreCase)) { return "North village"; } if (name.StartsWith("StoneCircle", StringComparison.OrdinalIgnoreCase)) { return "Stone circle"; } if (name.StartsWith("WoodVillage", StringComparison.OrdinalIgnoreCase)) { return "Draugr village"; } if (name.StartsWith("SunkenCrypt", StringComparison.OrdinalIgnoreCase)) { return "Crypt"; } if (name.StartsWith("ShipSetting", StringComparison.OrdinalIgnoreCase)) { return "Ship setting"; } if (name.StartsWith("Hildir_cave", StringComparison.OrdinalIgnoreCase)) { return "Howling Cavern"; } if (name.StartsWith("StoneHouse", StringComparison.OrdinalIgnoreCase)) { return "Stone house"; } if (name.StartsWith("GoblinCamp", StringComparison.OrdinalIgnoreCase)) { return "Fuling village"; } if (name.StartsWith("StoneTower", StringComparison.OrdinalIgnoreCase)) { return "Stone tower"; } if (name.StartsWith("StoneHenge", StringComparison.OrdinalIgnoreCase)) { return "Stone henge"; } if (name.StartsWith("CombatRuin", StringComparison.OrdinalIgnoreCase)) { return "Combat ruin"; } if (name.StartsWith("MorgenHole", StringComparison.OrdinalIgnoreCase)) { return "Putrid Hole"; } if (name.StartsWith("LumberCamp", StringComparison.OrdinalIgnoreCase)) { return "Lumber camp"; } if (name.StartsWith("Runestone", StringComparison.OrdinalIgnoreCase)) { return "Runestone"; } if (name.StartsWith("SwampRuin", StringComparison.OrdinalIgnoreCase)) { return "Swamp ruin"; } if (name.StartsWith("WoodHouse", StringComparison.OrdinalIgnoreCase)) { return "Wood house"; } if (name.StartsWith("TrollCave", StringComparison.OrdinalIgnoreCase)) { return "Troll Cave"; } if (name.StartsWith("SwampWell", StringComparison.OrdinalIgnoreCase)) { return "Swamp well"; } if (name.StartsWith("Waymarker", StringComparison.OrdinalIgnoreCase)) { return "Waymarker"; } if (name.StartsWith("ShipWreck", StringComparison.OrdinalIgnoreCase)) { return "Ship wreck"; } if (name.StartsWith("GoblinHut", StringComparison.OrdinalIgnoreCase)) { return "Goblin hut"; } if (name.StartsWith("FireHole", StringComparison.OrdinalIgnoreCase)) { return "Fire hole"; } if (name.StartsWith("WoodFarm", StringComparison.OrdinalIgnoreCase)) { return "Abandoned farm"; } if (name.StartsWith("SwampHut", StringComparison.OrdinalIgnoreCase)) { return "Swamp hut"; } if (name.StartsWith("MorkBorg", StringComparison.OrdinalIgnoreCase)) { return "Morkhalla"; } if (name.StartsWith("BearCave", StringComparison.OrdinalIgnoreCase)) { return "Bear cave"; } if (name.StartsWith("TheHole", StringComparison.OrdinalIgnoreCase)) { return "The hole"; } if (name.StartsWith("Dolmen", StringComparison.OrdinalIgnoreCase)) { return "Dolmen"; } if (name.StartsWith("TarPit", StringComparison.OrdinalIgnoreCase)) { return "Tar pit"; } if (name.StartsWith("DN_hut", StringComparison.OrdinalIgnoreCase)) { return "Dn hut"; } if (name.StartsWith("Grave", StringComparison.OrdinalIgnoreCase)) { return "Grave"; } if (name.StartsWith("Crypt", StringComparison.OrdinalIgnoreCase)) { return "Burial Chambers"; } if (name.StartsWith("Ruin", StringComparison.OrdinalIgnoreCase)) { return "Ruin"; } return null; } internal static bool IsService(string prefab) { if (Aio.TryGetValue(prefab ?? "", out var value)) { return value.Service; } return false; } internal static float EnterRadius(float actualRadius) { return Math.Max(5f, Math.Min(18f, actualRadius * 0.5f)); } internal static bool Entered(bool interiorLocation, bool inInterior, bool sameInterior, float horizontalDistanceSquared, float radius, float heightDifference) { if (!interiorLocation) { if (!inInterior && Math.Abs(heightDifference) <= 20f) { return horizontalDistanceSquared <= radius * radius; } return false; } return inInterior && sameInterior; } internal static bool KeepRecord(string kind) { if (!(kind == "Portal") && !(kind == "Dungeon")) { return kind == "Landmark"; } return true; } internal static float Alpha(bool crossed, float faded) { if (!crossed) { return 1f; } return faded; } internal static bool MatchingSavedPin(string label, string expected, string prefab) { if (string.IsNullOrWhiteSpace(label)) { return false; } string a = label.Trim(); if (string.Equals(a, expected, StringComparison.OrdinalIgnoreCase) || string.Equals(a, prefab, StringComparison.OrdinalIgnoreCase)) { return true; } if ((prefab ?? "").StartsWith("Crypt", StringComparison.OrdinalIgnoreCase)) { if (!string.Equals(a, "Burial Chamber", StringComparison.OrdinalIgnoreCase)) { return string.Equals(a, "Burial Chambers", StringComparison.OrdinalIgnoreCase); } return true; } return false; } } internal static class ResourceGrouping { internal static Dictionary<string, List<Record>> Build(IEnumerable<Record> input) { Dictionary<string, List<Record>> dictionary = new Dictionary<string, List<Record>>(); foreach (var item in from r in input group r by new { Kind = r.Kind, Name = ((r.Kind == "Ore") ? "" : (Policy.IsTar(r) ? "$tar" : r.Name)) }) { if (!Policy.Small(item.Key.Kind)) { foreach (Record item2 in item) { dictionary.Add(item2.Key, new List<Record> { item2 }); } continue; } float num = ((item.Key.Kind == "Ore" || item.Key.Name == "$tar") ? 32 : 12); float num2 = ((item.Key.Kind == "Ore" || item.Key.Name == "$tar") ? 12 : 4); Record[] list = item.OrderBy((Record r) => r.X).ThenBy<Record, string>((Record r) => r.Key, StringComparer.Ordinal).ToArray(); int[] parent = Enumerable.Range(0, list.Length).ToArray(); for (int num3 = 0; num3 < list.Length; num3++) { for (int num4 = num3 + 1; num4 < list.Length; num4++) { float num5 = list[num4].X - list[num3].X; if (num5 > num) { break; } float num6 = list[num4].Z - list[num3].Z; if (!(Math.Abs(list[num4].Y - list[num3].Y) > num2) && !(num5 * num5 + num6 * num6 > num * num)) { int num7 = Root(parent, num3); int num8 = Root(parent, num4); if (num7 != num8) { parent[num8] = num7; } } } } foreach (IGrouping<int, int> item3 in from i in Enumerable.Range(0, list.Length) group i by Root(parent, i)) { List<Record> list2 = item3.Select((int i) => list[i]).OrderBy<Record, string>((Record r) => r.Key, StringComparer.Ordinal).ToList(); dictionary.Add("cluster:" + list2[0].Key, list2); } } return dictionary; } internal static string Label(Record first, int count) { if (!(first.Kind == "Ore") && !Policy.IsTar(first)) { return first.Name + ((count > 1) ? (" x" + count) : ""); } if (count <= 1) { return ""; } return "×" + count; } private static int Root(int[] parent, int i) { while (parent[i] != i) { parent[i] = parent[parent[i]]; i = parent[i]; } return i; } } }