Decompiled source of MapTracker v1.0.4

BepInEx/plugins/MapTracker/MapTracker.dll

Decompiled 10 hours ago
using 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.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SoftReferenceableAssets;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.U2D;
using UnityEngine.UI;

[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("MapTracker")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: AssemblyInformationalVersion("1.0.4+ad37a50868880fae0a1f45ed01b0aa70af03b2a4")]
[assembly: AssemblyProduct("MapTracker")]
[assembly: AssemblyTitle("MapTracker")]
[assembly: AssemblyVersion("1.0.4.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 MapTracker
{
	public enum BuiltInFilterPreset
	{
		Default,
		Gathering,
		Exploration,
		Household
	}
	public static class BuiltInFilterPresets
	{
		private static readonly string[] PlantTokens = new string[21]
		{
			"berry", "berries", "bush", "mushroom", "thistle", "dandelion", "carrot", "turnip", "onion", "flax",
			"barley", "fiddlehead", "oat", "kale", "vine", "seed", "jotunpuff", "magecap", "smokepuff", "herb",
			"flower"
		};

		public static FilterPreset Build(IEnumerable<CatalogEntry> entries, BuiltInFilterPreset kind)
		{
			return new FilterPreset
			{
				types = entries.ToDictionary((CatalogEntry e) => e.key, (CatalogEntry e) => new FilterPresetType
				{
					selected = ((kind == BuiltInFilterPreset.Default) ? DefaultSelected(e) : Includes(e, kind)),
					keep = (Includes(e, kind) && !e.creature && e.category != "Dropped items" && e.category != "Plants and pickables" && (kind != BuiltInFilterPreset.Default || DiscoveryVisibility.KeepByDefault(e.dungeon, e.category)))
				})
			};
		}

		internal static bool DefaultSelected(CatalogEntry entry)
		{
			return DefaultSettings.Value("Types", entry.key.Replace('=', '_').Replace('[', '_').Replace(']', '_'), Includes(entry, BuiltInFilterPreset.Default));
		}

		internal static bool IsPlantMarker(CatalogEntry entry)
		{
			if (!(entry.category == "Plants and pickables"))
			{
				return entry.category == "Wild beehives";
			}
			return true;
		}

		private static bool Includes(CatalogEntry entry, BuiltInFilterPreset kind)
		{
			if (entry.technical)
			{
				return false;
			}
			switch (kind)
			{
			case BuiltInFilterPreset.Default:
				if (!entry.dungeon && !(entry.category == "Portals") && !entry.creature)
				{
					if (entry.category == "Ore")
					{
						return (entry.products ?? new string[0]).Any((string p) => !string.Equals(p, "Stone", StringComparison.OrdinalIgnoreCase));
					}
					return false;
				}
				return true;
			case BuiltInFilterPreset.Gathering:
				return IsGrowingCollectible(entry);
			case BuiltInFilterPreset.Exploration:
				if (!entry.dungeon && !(entry.category == "Portals") && !(entry.category == "Locations") && !HasComponent(entry, "Trader"))
				{
					return HasComponent(entry, "OfferingBowl");
				}
				return true;
			case BuiltInFilterPreset.Household:
				if (!entry.creature && !(entry.category == "Portals") && !(entry.category == "Sap collectors"))
				{
					if (entry.category == "Player structures")
					{
						return HasComponent(entry, "Beehive");
					}
					return false;
				}
				return true;
			default:
				return false;
			}
		}

		private static bool HasComponent(CatalogEntry entry, string component)
		{
			if (entry.components != null)
			{
				return entry.components.Contains(component);
			}
			return false;
		}

		private static bool IsGrowingCollectible(CatalogEntry entry)
		{
			if (entry.category == "Wild beehives")
			{
				return true;
			}
			if (entry.category != "Plants and pickables")
			{
				return false;
			}
			return new string[1] { entry.prefab ?? "" }.Concat(entry.products ?? new string[0]).Any((string identity) => PlantTokens.Any((string token) => identity.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0));
		}
	}
	[Serializable]
	public sealed class CatalogEntry
	{
		public string key;

		public string prefab;

		public string name;

		public string category;

		public string source;

		public string[] components;

		public string[] products;

		public bool creature;

		public bool dungeon;

		public bool renewable;

		public bool playerPiece;

		public bool technical;

		public float respawnMinutes;

		[NonSerialized]
		internal ConfigEntry<bool> Selected;

		[NonSerialized]
		internal ConfigEntry<bool> KeepVisible;

		[NonSerialized]
		internal Sprite Icon;

		internal string Label
		{
			get
			{
				string text = (dungeon ? DungeonNames.Get(prefab, russian: false) : null);
				if (text != null)
				{
					return Plugin.Text(DungeonNames.Get(prefab, russian: true), text);
				}
				string text2 = Plugin.Localize(name);
				bool flag = text2 == "[" + (name ?? "").TrimStart(new char[1] { '$' }) + "]";
				if (!(string.IsNullOrWhiteSpace(text2) || text2.StartsWith("$", StringComparison.Ordinal) || flag) && !(text2 == prefab))
				{
					return text2;
				}
				return ReadableName(string.IsNullOrWhiteSpace(prefab) ? key : prefab);
			}
		}

		internal string FilterLabel
		{
			get
			{
				if (!(category == "Dropped items"))
				{
					if (!(category == "Plants and pickables") || components == null || !components.Contains("Pickable"))
					{
						return Label;
					}
					return Label + ((prefab != null && prefab.EndsWith("Bush", StringComparison.OrdinalIgnoreCase)) ? Plugin.Text(" (куст)", " (bush)") : Plugin.Text(" (сбор)", " (pickable)"));
				}
				return Label + Plugin.Text(" (на земле)", " (dropped)");
			}
		}

		private static string ReadableName(string value)
		{
			switch (value)
			{
			case "Crypt2":
			case "Crypt3":
			case "Crypt4":
				return Plugin.Text("Погребальные камеры", "Burial Chambers");
			case "SunkenCrypt4":
				return Plugin.Text("Затонувший склеп", "Sunken Crypt");
			case "TrollCave02":
				return Plugin.Text("Пещера тролля", "Troll Cave");
			case "MountainCave02":
				return Plugin.Text("Морозная пещера", "Frost Cave");
			case "Mistlands_DvergrTownEntrance1":
			case "Mistlands_DvergrTownEntrance2":
				return Plugin.Text("Заражённые шахты", "Infested Mines");
			case "Mistlands_DvergrBossEntrance1":
				return Plugin.Text("Цитадель Королевы", "Queen's Citadel");
			case "MorgenHole2":
			case "MorgenHole1":
			case "MorgenHole3":
				return Plugin.Text("Пещера моргена", "Morgen Cave");
			case "Hildir_cave":
				return Plugin.Text("Воющая пещера", "Howling Cavern");
			case "Hildir_crypt":
				return Plugin.Text("Тлеющая гробница", "Smouldering Tomb");
			default:
				return Regex.Replace(Regex.Replace(Regex.Replace(value ?? "", "([a-z])([A-Z])", "$1 $2"), "([a-zA-Z])([0-9])", "$1 $2").Replace('_', ' '), "\\s+", " ").Trim();
			}
		}
	}
	[Serializable]
	public sealed class CatalogDocument
	{
		public int schema = 1;

		public string modVersion;

		public string gameVersion;

		public string generatedUtc;

		public List<CatalogEntry> entries;

		public List<string> warnings;
	}
	internal sealed class Catalog
	{
		internal readonly List<CatalogEntry> Entries = new List<CatalogEntry>();

		internal readonly Dictionary<int, CatalogEntry> Prefabs = new Dictionary<int, CatalogEntry>();

		internal readonly Dictionary<int, CatalogEntry> Locations = new Dictionary<int, CatalogEntry>();

		private readonly Dictionary<string, CatalogEntry> liveTypes = new Dictionary<string, CatalogEntry>();

		private readonly Dictionary<string, CatalogEntry> cachedTypes = new Dictionary<string, CatalogEntry>();

		internal int Processed;

		internal int Total;

		internal string Status = "Waiting for game registries";

		private readonly Plugin host;

		private readonly List<string> warnings = new List<string>();

		private ZNetScene scene;

		private Coroutine scan;

		private readonly ConfigEntry<int> keepDefaultsRevision;

		private readonly ConfigEntry<int> plantKeepRevision;

		internal bool Ready { get; private set; }

		internal string ExportPath => Path.Combine(Paths.ConfigPath, "MapTracker", "catalog.json");

		internal Catalog(Plugin plugin)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			host = plugin;
			keepDefaultsRevision = ((BaseUnityPlugin)host).Config.Bind<int>("Internal", "Keep discovered defaults revision", 0, new ConfigDescription("One-time application of the portals-and-dungeons memory preset.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}));
			plantKeepRevision = ((BaseUnityPlugin)host).Config.Bind<int>("Internal", "Plant keep defaults revision", 0, new ConfigDescription("One-time reset of Plants and pickables to nearby-only markers.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}));
		}

		internal void Tick()
		{
			if ((Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null || (Object)(object)scene == (Object)(object)ZNetScene.instance)
			{
				return;
			}
			if (scan != null)
			{
				((MonoBehaviour)host).StopCoroutine(scan);
			}
			scene = ZNetScene.instance;
			Ready = false;
			Entries.Clear();
			Prefabs.Clear();
			Locations.Clear();
			warnings.Clear();
			liveTypes.Clear();
			cachedTypes.Clear();
			try
			{
				if (File.Exists(ExportPath))
				{
					CatalogDocument catalogDocument = DataJson.Read<CatalogDocument>(File.ReadAllText(ExportPath, Encoding.UTF8));
					if (catalogDocument != null && catalogDocument.schema == 1 && catalogDocument.entries != null)
					{
						foreach (CatalogEntry entry in catalogDocument.entries)
						{
							if (entry != null && !string.IsNullOrEmpty(entry.key))
							{
								cachedTypes[entry.key] = entry;
							}
						}
					}
				}
			}
			catch (Exception e)
			{
				host.Report("Cached catalog could not be read; collecting fresh definitions", e);
			}
			scan = ((MonoBehaviour)host).StartCoroutine(Scan(scene, ZoneSystem.instance));
		}

		private IEnumerator Scan(ZNetScene current, ZoneSystem world)
		{
			yield return null;
			yield return null;
			List<GameObject> list = (from p in current.m_prefabs.Concat(current.m_nonNetViewPrefabs).Concat(ObjectDB.instance.m_items)
				where (Object)(object)p != (Object)null
				group p by ((Object)p).name into g
				select g.First()).ToList();
			List<ZoneLocation> locations = world.m_locations.Where((ZoneLocation l) => l.m_enable && l.m_prefab.IsValid).ToList();
			Processed = 0;
			Total = list.Count + locations.Count;
			long timestamp = Stopwatch.GetTimestamp();
			foreach (GameObject item in list)
			{
				if (!((Object)(object)current != (Object)(object)ZNetScene.instance))
				{
					try
					{
						Add(ReadPrefab(item), Prefabs);
					}
					catch (Exception ex)
					{
						warnings.Add(((Object)item).name + ": " + ex.Message);
					}
					Status = ((Object)item).name;
					Processed++;
					if (!ScanTimeBudget.WithinBudget(timestamp, host.ScanBudget.Value))
					{
						yield return null;
						timestamp = Stopwatch.GetTimestamp();
					}
					continue;
				}
				yield break;
			}
			foreach (ZoneLocation location in locations)
			{
				if ((Object)(object)current != (Object)(object)ZNetScene.instance)
				{
					yield break;
				}
				Status = location.m_prefabName;
				SoftReference<GameObject> reference = location.m_prefab;
				bool flag = false;
				try
				{
					reference.LoadAsync();
					flag = true;
				}
				catch (Exception ex2)
				{
					warnings.Add(Status + ": " + ex2.Message);
				}
				if (flag)
				{
					try
					{
						float deadline = Time.realtimeSinceStartup + 15f;
						while (!reference.IsLoaded && Time.realtimeSinceStartup < deadline)
						{
							if (!((Object)(object)current != (Object)(object)ZNetScene.instance))
							{
								yield return null;
								continue;
							}
							yield break;
						}
						if (reference.IsLoaded && (Object)(object)reference.Asset != (Object)null)
						{
							ReadLocationSafe(location, reference.Asset);
						}
						else
						{
							warnings.Add(Status + ": definition loading timed out");
						}
					}
					finally
					{
						reference.Release();
					}
				}
				Processed++;
				yield return null;
			}
			if (host.PresetRevision.Value == 0)
			{
				ApplyMinimalPreset();
			}
			keepDefaultsRevision.Value = 1;
			plantKeepRevision.Value = 1;
			Ready = true;
			Status = "Ready";
			scan = null;
			((BaseUnityPlugin)host).Config.Save();
			Export();
		}

		private void Add(CatalogEntry entry, Dictionary<int, CatalogEntry> index)
		{
			BindSettings(entry);
			Entries.Add(entry);
			index[StringExtensionMethods.GetStableHashCode(entry.prefab)] = entry;
			liveTypes[entry.key] = entry;
		}

		internal CatalogEntry GetSavedDefinition(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return null;
			}
			if (liveTypes.TryGetValue(key, out var value))
			{
				return value;
			}
			if (Ready || !cachedTypes.TryGetValue(key, out var value2))
			{
				return null;
			}
			if (value2.Selected == null)
			{
				BindSettings(value2);
				object obj;
				if (!string.IsNullOrEmpty(value2.prefab))
				{
					ZNetScene instance = ZNetScene.instance;
					obj = ((instance != null) ? instance.GetPrefab(value2.prefab) : null);
				}
				else
				{
					obj = null;
				}
				GameObject val = (GameObject)obj;
				CatalogEntry catalogEntry = value2;
				object obj2;
				if (!value2.creature)
				{
					obj2 = ((val == null) ? null : val.GetComponent<Piece>()?.m_icon);
					if (obj2 == null)
					{
						if (val == null)
						{
							obj2 = null;
						}
						else
						{
							ItemDrop component = val.GetComponent<ItemDrop>();
							obj2 = ((component != null) ? component.m_itemData.GetIcon() : null);
						}
					}
				}
				else
				{
					obj2 = CreatureIconResolver.Resolve(val, value2.prefab);
				}
				catalogEntry.Icon = (Sprite)obj2;
			}
			return value2;
		}

		private void BindSettings(CatalogEntry entry)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			bool saveOnConfigSet = ((BaseUnityPlugin)host).Config.SaveOnConfigSet;
			((BaseUnityPlugin)host).Config.SaveOnConfigSet = false;
			try
			{
				string text = entry.key.Replace('=', '_').Replace('[', '_').Replace(']', '_');
				host.MapCategories.Register(entry.category);
				entry.Selected = ((BaseUnityPlugin)host).Config.Bind<bool>("Types", text, BuiltInFilterPresets.DefaultSelected(entry), new ConfigDescription(entry.prefab, (AcceptableValueBase)null, new object[1]
				{
					new ConfigurationManagerAttributes
					{
						Browsable = false
					}
				}));
				if (!entry.creature && entry.category != "Dropped items")
				{
					bool flag = DefaultSettings.Value("Keep discovered markers", text, DiscoveryVisibility.KeepByDefault(entry.dungeon, entry.category));
					entry.KeepVisible = ((BaseUnityPlugin)host).Config.Bind<bool>("Keep discovered markers", text, flag, new ConfigDescription("Keep this type visible after leaving the client-loaded detection area. Turning this off hides remembered markers outside that area without deleting discoveries.", (AcceptableValueBase)null, new object[1]
					{
						new ConfigurationManagerAttributes
						{
							Browsable = false
						}
					}));
					if (keepDefaultsRevision.Value == 0)
					{
						entry.KeepVisible.Value = flag;
					}
					if (plantKeepRevision.Value == 0 && entry.category == "Plants and pickables")
					{
						entry.KeepVisible.Value = false;
					}
				}
			}
			finally
			{
				((BaseUnityPlugin)host).Config.SaveOnConfigSet = saveOnConfigSet;
			}
		}

		internal void ApplyMinimalPreset()
		{
			bool saveOnConfigSet = ((BaseUnityPlugin)host).Config.SaveOnConfigSet;
			((BaseUnityPlugin)host).Config.SaveOnConfigSet = false;
			try
			{
				foreach (CatalogEntry entry in Entries)
				{
					entry.Selected.Value = BuiltInFilterPresets.DefaultSelected(entry);
					if (entry.KeepVisible != null)
					{
						entry.KeepVisible.Value = DefaultSettings.Value("Keep discovered markers", ((ConfigEntryBase)entry.KeepVisible).Definition.Key, DiscoveryVisibility.KeepByDefault(entry.dungeon, entry.category));
					}
				}
				host.Hostile.Value = true;
				host.Friendly.Value = false;
				host.Animals.Value = false;
				host.Tamed.Value = false;
				host.PresetRevision.Value = 1;
			}
			finally
			{
				((BaseUnityPlugin)host).Config.SaveOnConfigSet = saveOnConfigSet;
			}
			((BaseUnityPlugin)host).Config.Save();
		}

		internal CatalogEntry GetLegacyDungeon(string name)
		{
			string key = "legacy:" + name;
			CatalogEntry catalogEntry = Entries.FirstOrDefault((CatalogEntry e) => e.key == key);
			if (catalogEntry != null)
			{
				return catalogEntry;
			}
			catalogEntry = new CatalogEntry
			{
				key = key,
				prefab = name,
				name = name,
				category = "Dungeons",
				dungeon = true,
				source = "AutoMapPins saved map pin",
				products = new string[0],
				components = new string[0]
			};
			Add(catalogEntry, new Dictionary<int, CatalogEntry>());
			return catalogEntry;
		}

		private static string ItemName(GameObject go)
		{
			return ((go == null) ? null : go.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_name) ?? ((go != null) ? ((Object)go).name : null) ?? "";
		}

		private static string[] Products(DropTable table)
		{
			return (from d in table?.m_drops?.Where((DropData d) => (Object)(object)d.m_item != (Object)null)
				select ((Object)d.m_item).name).Distinct().ToArray() ?? new string[0];
		}

		private static CatalogEntry ReadPrefab(GameObject go)
		{
			CatalogEntry catalogEntry = new CatalogEntry
			{
				key = "prefab:" + ((Object)go).name,
				prefab = ((Object)go).name,
				name = ((Object)go).name,
				category = "Other",
				source = "ZNetScene/ObjectDB",
				products = new string[0],
				components = (from c in go.GetComponents<Component>()
					where (Object)(object)c != (Object)null
					select ((object)c).GetType().Name).ToArray()
			};
			Character component = go.GetComponent<Character>();
			Piece component2 = go.GetComponent<Piece>();
			Pickable component3 = go.GetComponent<Pickable>();
			MineRock component4 = go.GetComponent<MineRock>();
			MineRock5 component5 = go.GetComponent<MineRock5>();
			Container component6 = go.GetComponent<Container>();
			ItemDrop component7 = go.GetComponent<ItemDrop>();
			if ((Object)(object)component != (Object)null)
			{
				catalogEntry.category = "Creatures";
				catalogEntry.creature = true;
				catalogEntry.name = component.m_name;
			}
			else if ((Object)(object)component4 != (Object)null)
			{
				catalogEntry.category = "Ore";
				catalogEntry.name = component4.m_name;
				catalogEntry.products = Products(component4.m_dropItems);
			}
			else if ((Object)(object)component5 != (Object)null)
			{
				catalogEntry.category = "Ore";
				catalogEntry.name = component5.m_name;
				catalogEntry.products = Products(component5.m_dropItems);
			}
			else if ((Object)(object)component3 != (Object)null)
			{
				catalogEntry.category = "Plants and pickables";
				catalogEntry.name = (string.IsNullOrEmpty(component3.m_overrideName) ? ItemName(component3.m_itemPrefab) : component3.m_overrideName);
				catalogEntry.products = (((Object)(object)component3.m_itemPrefab == (Object)null) ? new string[0] : new string[1] { ((Object)component3.m_itemPrefab).name });
				catalogEntry.respawnMinutes = component3.m_respawnTimeMinutes;
				catalogEntry.renewable = catalogEntry.respawnMinutes > 0f;
			}
			else if ((Object)(object)component6 != (Object)null)
			{
				catalogEntry.category = "Containers";
				catalogEntry.name = component6.m_name;
				catalogEntry.products = Products(component6.m_defaultItems);
			}
			else if ((Object)(object)component7 != (Object)null)
			{
				catalogEntry.category = "Dropped items";
				catalogEntry.name = ItemName(go);
				catalogEntry.Icon = component7.m_itemData.GetIcon();
			}
			else if ((Object)(object)component2 != (Object)null)
			{
				catalogEntry.category = "Player structures";
				catalogEntry.playerPiece = true;
				catalogEntry.name = component2.m_name;
				catalogEntry.Icon = component2.m_icon;
			}
			else if ((Object)(object)go.GetComponent<TreeBase>() != (Object)null || (Object)(object)go.GetComponent<TreeLog>() != (Object)null)
			{
				catalogEntry.category = "Trees";
			}
			else if ((Object)(object)go.GetComponent<Destructible>() != (Object)null)
			{
				catalogEntry.category = "Destructibles";
			}
			if (((Object)go).name == "dvergrprops_crate_long")
			{
				catalogEntry.category = "Dvergr loot";
				catalogEntry.name = "$item_dvergrneedle";
				catalogEntry.products = new string[1] { "DvergrNeedle" };
			}
			if (((Object)go).name == "DvergrNeedle" && (Object)(object)component7 != (Object)null)
			{
				catalogEntry.category = "Dvergr loot";
			}
			if (((Object)go).name == "Beehive" && (Object)(object)component2 == (Object)null)
			{
				catalogEntry.category = "Wild beehives";
				catalogEntry.name = "$item_queenbee";
			}
			SapCollector component8 = go.GetComponent<SapCollector>();
			if (component8 != null)
			{
				catalogEntry.category = "Sap collectors";
				catalogEntry.name = component8.m_name;
			}
			if ((Object)(object)go.GetComponent<TeleportWorld>() != (Object)null)
			{
				catalogEntry.category = "Portals";
			}
			if (((Object)go).name.IndexOf("YggaRoot", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				catalogEntry.category = "Sap roots";
			}
			if (catalogEntry.creature)
			{
				catalogEntry.Icon = CreatureIconResolver.Resolve(go, catalogEntry.prefab);
			}
			if (catalogEntry.category == "Ore" && (string.IsNullOrWhiteSpace(catalogEntry.name) || catalogEntry.name == ((Object)go).name || catalogEntry.name == "Rock" || catalogEntry.name == "$piece_rock"))
			{
				string text = catalogEntry.products.FirstOrDefault((string p) => p != "Stone") ?? catalogEntry.products.FirstOrDefault();
				if (text != null)
				{
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text);
					catalogEntry.name = ItemName(itemPrefab);
					object icon;
					if (itemPrefab == null)
					{
						icon = null;
					}
					else
					{
						ItemDrop component9 = itemPrefab.GetComponent<ItemDrop>();
						icon = ((component9 != null) ? component9.m_itemData.GetIcon() : null);
					}
					catalogEntry.Icon = (Sprite)icon;
				}
			}
			if (catalogEntry.name == ((Object)go).name || string.IsNullOrWhiteSpace(catalogEntry.name))
			{
				Hoverable component10 = go.GetComponent<Hoverable>();
				if (component10 != null)
				{
					try
					{
						string hoverName = component10.GetHoverName();
						if (!string.IsNullOrWhiteSpace(hoverName))
						{
							catalogEntry.name = hoverName;
						}
					}
					catch
					{
					}
				}
			}
			catalogEntry.technical = catalogEntry.category == "Other" && (catalogEntry.components.Any(delegate(string c)
			{
				switch (c)
				{
				default:
					return c == "ZSFX";
				case "Projectile":
				case "Aoe":
				case "TimedDestruction":
				case "ParticleSystem":
					return true;
				}
			}) || ((Object)go).name.StartsWith("sfx_", StringComparison.OrdinalIgnoreCase) || ((Object)go).name.StartsWith("vfx_", StringComparison.OrdinalIgnoreCase) || ((Object)go).name.StartsWith("fx_", StringComparison.OrdinalIgnoreCase));
			if ((Object)(object)catalogEntry.Icon == (Object)null && catalogEntry.products.Length != 0)
			{
				GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab(catalogEntry.products[0]);
				ItemDrop val = ((itemPrefab2 != null) ? itemPrefab2.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val != (Object)null)
				{
					catalogEntry.Icon = val.m_itemData.GetIcon();
				}
			}
			return catalogEntry;
		}

		private void ReadLocationSafe(ZoneLocation location, GameObject go)
		{
			try
			{
				Location component = go.GetComponent<Location>();
				Teleport val = go.GetComponentsInChildren<Teleport>(true).FirstOrDefault();
				CatalogEntry catalogEntry = new CatalogEntry();
				catalogEntry.key = "location:" + location.m_prefabName;
				catalogEntry.prefab = location.m_prefabName;
				catalogEntry.name = (((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.m_discoverLabel)) ? component.m_discoverLabel : location.m_prefabName);
				catalogEntry.source = "ZoneSystem";
				catalogEntry.category = "Locations";
				catalogEntry.products = new string[0];
				catalogEntry.components = new string[1] { "Location" };
				CatalogEntry catalogEntry2 = catalogEntry;
				catalogEntry2.dungeon = (Object)(object)val != (Object)null || (Object)(object)go.GetComponentInChildren<DungeonGenerator>(true) != (Object)null;
				if (catalogEntry2.dungeon)
				{
					catalogEntry2.category = "Dungeons";
					if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(val.m_enterText))
					{
						catalogEntry2.name = val.m_enterText;
					}
				}
				Add(catalogEntry2, Locations);
			}
			catch (Exception ex)
			{
				warnings.Add(location.m_prefabName + ": " + ex.Message);
			}
		}

		internal void Export()
		{
			if (!Ready)
			{
				host.Report("Catalog is still being collected; export deferred until complete.");
				return;
			}
			try
			{
				CatalogDocument value = new CatalogDocument
				{
					modVersion = "1.0.4",
					gameVersion = Version.GetVersionString(false),
					generatedUtc = DateTime.UtcNow.ToString("o"),
					entries = Entries,
					warnings = warnings
				};
				Directory.CreateDirectory(Path.GetDirectoryName(ExportPath));
				string text = ExportPath + ".tmp";
				string text2 = DataJson.Write(value, pretty: true);
				if (text2.IndexOf("\"entries\"", StringComparison.Ordinal) < 0)
				{
					throw new InvalidOperationException("Serializer omitted the catalog entries.");
				}
				File.WriteAllText(text, text2, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
				if (File.Exists(ExportPath))
				{
					File.Replace(text, ExportPath, ExportPath + ".bak");
				}
				else
				{
					File.Move(text, ExportPath);
				}
			}
			catch (Exception e)
			{
				host.Report("Catalog export failed", e);
			}
		}
	}
	internal sealed class ClusterPoint
	{
		internal float X;

		internal float Y;

		internal string Kind;

		internal float WorldX;

		internal float WorldZ;

		internal float HalfWidth;

		internal float HalfHeight;
	}
	internal static class ClusterMath
	{
		private sealed class FootprintGroup
		{
			internal readonly List<int> Members = new List<int>();

			internal FootprintGroup Parent;

			internal float MinX;

			internal float MaxX;

			internal float MinY;

			internal float MaxY;

			internal float MinWorldX;

			internal float MaxWorldX;

			internal float MinWorldZ;

			internal float MaxWorldZ;

			internal float HalfWidth;

			internal float HalfHeight;

			internal FootprintGroup Root()
			{
				if (Parent != null)
				{
					Parent = Parent.Root();
				}
				return Parent ?? this;
			}

			internal void Add(ClusterPoint point, int id)
			{
				if (Members.Count == 0)
				{
					MinX = (MaxX = point.X);
					MinY = (MaxY = point.Y);
					MinWorldX = (MaxWorldX = point.WorldX);
					MinWorldZ = (MaxWorldZ = point.WorldZ);
				}
				else
				{
					MinX = Math.Min(MinX, point.X);
					MaxX = Math.Max(MaxX, point.X);
					MinY = Math.Min(MinY, point.Y);
					MaxY = Math.Max(MaxY, point.Y);
					MinWorldX = Math.Min(MinWorldX, point.WorldX);
					MaxWorldX = Math.Max(MaxWorldX, point.WorldX);
					MinWorldZ = Math.Min(MinWorldZ, point.WorldZ);
					MaxWorldZ = Math.Max(MaxWorldZ, point.WorldZ);
				}
				HalfWidth = Math.Max(HalfWidth, point.HalfWidth);
				HalfHeight = Math.Max(HalfHeight, point.HalfHeight);
				Members.Add(id);
			}

			private bool BoundsFit(float minX, float maxX, float minY, float maxY, float minWorldX, float maxWorldX, float minWorldZ, float maxWorldZ, float screenLimit, float worldLimit)
			{
				float num = Math.Max(MaxX, maxX) - Math.Min(MinX, minX);
				float num2 = Math.Max(MaxY, maxY) - Math.Min(MinY, minY);
				float num3 = Math.Max(MaxWorldX, maxWorldX) - Math.Min(MinWorldX, minWorldX);
				float num4 = Math.Max(MaxWorldZ, maxWorldZ) - Math.Min(MinWorldZ, minWorldZ);
				if (num * num + num2 * num2 <= screenLimit * screenLimit)
				{
					return num3 * num3 + num4 * num4 <= worldLimit * worldLimit;
				}
				return false;
			}

			internal bool Fits(ClusterPoint point, List<ClusterPoint> points, float gap, float worldLimit)
			{
				float screenLimit = 2f * (2f * Math.Max(Math.Max(HalfWidth, HalfHeight), Math.Max(point.HalfWidth, point.HalfHeight)) + gap);
				if (!BoundsFit(point.X, point.X, point.Y, point.Y, point.WorldX, point.WorldX, point.WorldZ, point.WorldZ, screenLimit, worldLimit))
				{
					return false;
				}
				if (point.X + point.HalfWidth + gap < MinX - HalfWidth || point.X - point.HalfWidth - gap > MaxX + HalfWidth || point.Y + point.HalfHeight + gap < MinY - HalfHeight || point.Y - point.HalfHeight - gap > MaxY + HalfHeight)
				{
					return false;
				}
				foreach (int member in Members)
				{
					ClusterPoint clusterPoint = points[member];
					if (Math.Abs(point.X - clusterPoint.X) <= point.HalfWidth + clusterPoint.HalfWidth + gap && Math.Abs(point.Y - clusterPoint.Y) <= point.HalfHeight + clusterPoint.HalfHeight + gap)
					{
						return true;
					}
				}
				return false;
			}

			internal bool CanMerge(FootprintGroup other, float gap, float worldLimit)
			{
				float screenLimit = 2f * (2f * Math.Max(Math.Max(HalfWidth, HalfHeight), Math.Max(other.HalfWidth, other.HalfHeight)) + gap);
				return BoundsFit(other.MinX, other.MaxX, other.MinY, other.MaxY, other.MinWorldX, other.MaxWorldX, other.MinWorldZ, other.MaxWorldZ, screenLimit, worldLimit);
			}
		}

		private sealed class Extent
		{
			internal readonly List<int> Members = new List<int>();

			internal float MinX;

			internal float MaxX;

			internal float MinY;

			internal float MaxY;

			internal float MinWorldX;

			internal float MaxWorldX;

			internal float MinWorldZ;

			internal float MaxWorldZ;

			internal bool Fits(ClusterPoint p, List<ClusterPoint> points, float distance, float screenDiameter, float worldDiameter)
			{
				float num = Math.Max(MaxX, p.X) - Math.Min(MinX, p.X);
				float num2 = Math.Max(MaxY, p.Y) - Math.Min(MinY, p.Y);
				float num3 = Math.Max(MaxWorldX, p.WorldX) - Math.Min(MinWorldX, p.WorldX);
				float num4 = Math.Max(MaxWorldZ, p.WorldZ) - Math.Min(MinWorldZ, p.WorldZ);
				if (num * num + num2 * num2 > screenDiameter * screenDiameter || num3 * num3 + num4 * num4 > worldDiameter * worldDiameter)
				{
					return false;
				}
				foreach (int member in Members)
				{
					float num5 = p.X - points[member].X;
					float num6 = p.Y - points[member].Y;
					if (num5 * num5 + num6 * num6 <= distance * distance)
					{
						return true;
					}
				}
				return false;
			}

			internal void Add(ClusterPoint p, int i)
			{
				if (Members.Count == 0)
				{
					MinX = (MaxX = p.X);
					MinY = (MaxY = p.Y);
					MinWorldX = (MaxWorldX = p.WorldX);
					MinWorldZ = (MaxWorldZ = p.WorldZ);
				}
				else
				{
					MinX = Math.Min(MinX, p.X);
					MaxX = Math.Max(MaxX, p.X);
					MinY = Math.Min(MinY, p.Y);
					MaxY = Math.Max(MaxY, p.Y);
					MinWorldX = Math.Min(MinWorldX, p.WorldX);
					MaxWorldX = Math.Max(MaxWorldX, p.WorldX);
					MinWorldZ = Math.Min(MinWorldZ, p.WorldZ);
					MaxWorldZ = Math.Max(MaxWorldZ, p.WorldZ);
				}
				Members.Add(i);
			}
		}

		private struct Cell : IEquatable<Cell>
		{
			internal int X;

			internal int Y;

			internal string Kind;

			public bool Equals(Cell other)
			{
				if (X == other.X && Y == other.Y)
				{
					return Kind == other.Kind;
				}
				return false;
			}

			public override bool Equals(object other)
			{
				if (other is Cell)
				{
					return Equals((Cell)other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (((X * 397) ^ Y) * 397) ^ (Kind?.GetHashCode() ?? 0);
			}
		}

		internal static List<List<int>> BuildOverlapping(List<ClusterPoint> points, float gap, int minimum, float worldLimit)
		{
			if (gap < 0f || worldLimit <= 0f)
			{
				throw new ArgumentOutOfRangeException("worldLimit");
			}
			float num = 1f;
			foreach (ClusterPoint point in points)
			{
				num = Math.Max(num, 2f * Math.Max(point.HalfWidth, point.HalfHeight) + gap);
			}
			Dictionary<Cell, List<FootprintGroup>> dictionary = new Dictionary<Cell, List<FootprintGroup>>();
			List<FootprintGroup> list = new List<FootprintGroup>();
			HashSet<FootprintGroup> hashSet = new HashSet<FootprintGroup>();
			List<FootprintGroup> list2 = new List<FootprintGroup>();
			for (int i = 0; i < points.Count; i++)
			{
				ClusterPoint clusterPoint = points[i];
				int num2 = (int)Math.Floor(clusterPoint.X / num);
				int num3 = (int)Math.Floor(clusterPoint.Y / num);
				hashSet.Clear();
				list2.Clear();
				for (int j = -2; j <= 2; j++)
				{
					for (int k = -2; k <= 2; k++)
					{
						if (!dictionary.TryGetValue(new Cell
						{
							X = num2 + j,
							Y = num3 + k,
							Kind = clusterPoint.Kind
						}, out var value))
						{
							continue;
						}
						foreach (FootprintGroup item in value)
						{
							FootprintGroup footprintGroup = item.Root();
							if (hashSet.Add(footprintGroup) && footprintGroup.Fits(clusterPoint, points, gap, worldLimit))
							{
								list2.Add(footprintGroup);
							}
						}
					}
				}
				FootprintGroup footprintGroup2;
				if (list2.Count == 0)
				{
					footprintGroup2 = new FootprintGroup();
					list.Add(footprintGroup2);
					Cell key = new Cell
					{
						X = num2,
						Y = num3,
						Kind = clusterPoint.Kind
					};
					if (!dictionary.TryGetValue(key, out var value2))
					{
						dictionary.Add(key, value2 = new List<FootprintGroup>());
					}
					value2.Add(footprintGroup2);
				}
				else
				{
					footprintGroup2 = list2[0];
				}
				footprintGroup2.Add(clusterPoint, i);
				for (int l = 1; l < list2.Count; l++)
				{
					FootprintGroup footprintGroup3 = list2[l];
					if (!footprintGroup2.CanMerge(footprintGroup3, gap, worldLimit))
					{
						continue;
					}
					foreach (int member in footprintGroup3.Members)
					{
						footprintGroup2.Add(points[member], member);
					}
					footprintGroup3.Parent = footprintGroup2;
				}
			}
			List<List<int>> list3 = new List<List<int>>();
			foreach (FootprintGroup item2 in list)
			{
				if (item2.Parent == null && item2.Members.Count >= minimum)
				{
					list3.Add(item2.Members);
				}
			}
			return list3;
		}

		internal static List<List<int>> BuildBounded(List<ClusterPoint> points, float distance, int minimum, float screenDiameter, float worldDiameter)
		{
			if (screenDiameter <= 0f || worldDiameter <= 0f)
			{
				throw new ArgumentOutOfRangeException("screenDiameter");
			}
			List<List<int>> list = new List<List<int>>();
			foreach (List<int> item in Build(points, distance, minimum))
			{
				List<Extent> list2 = new List<Extent>();
				foreach (int item2 in item)
				{
					Extent extent = null;
					foreach (Extent item3 in list2)
					{
						if (item3.Fits(points[item2], points, distance, screenDiameter, worldDiameter))
						{
							extent = item3;
							break;
						}
					}
					if (extent == null)
					{
						extent = new Extent();
						list2.Add(extent);
					}
					extent.Add(points[item2], item2);
				}
				foreach (Extent item4 in list2)
				{
					if (item4.Members.Count >= minimum)
					{
						list.Add(item4.Members);
					}
				}
			}
			return list;
		}

		private static int Root(int[] parents, int index)
		{
			while (parents[index] != index)
			{
				parents[index] = parents[parents[index]];
				index = parents[index];
			}
			return index;
		}

		internal static List<List<int>> Build(List<ClusterPoint> points, float distance, int minimum)
		{
			if (distance <= 0f)
			{
				throw new ArgumentOutOfRangeException("distance");
			}
			Dictionary<Cell, List<int>> dictionary = new Dictionary<Cell, List<int>>();
			int[] array = new int[points.Count];
			float num = distance * distance;
			double num2 = (double)distance / Math.Sqrt(2.0);
			for (int i = 0; i < points.Count; i++)
			{
				array[i] = i;
				ClusterPoint clusterPoint = points[i];
				int num3 = (int)Math.Floor((double)clusterPoint.X / num2);
				int num4 = (int)Math.Floor((double)clusterPoint.Y / num2);
				for (int j = -2; j <= 2; j++)
				{
					for (int k = -2; k <= 2; k++)
					{
						Cell key = new Cell
						{
							X = num3 + j,
							Y = num4 + k,
							Kind = clusterPoint.Kind
						};
						if (!dictionary.TryGetValue(key, out var value))
						{
							continue;
						}
						foreach (int item in value)
						{
							float num5 = clusterPoint.X - points[item].X;
							float num6 = clusterPoint.Y - points[item].Y;
							if (num5 * num5 + num6 * num6 <= num)
							{
								array[Root(array, i)] = Root(array, item);
								break;
							}
						}
					}
				}
				Cell key2 = new Cell
				{
					X = num3,
					Y = num4,
					Kind = clusterPoint.Kind
				};
				if (!dictionary.TryGetValue(key2, out var value2))
				{
					value2 = (dictionary[key2] = new List<int>());
				}
				value2.Add(i);
			}
			Dictionary<int, List<int>> dictionary2 = new Dictionary<int, List<int>>();
			for (int l = 0; l < points.Count; l++)
			{
				int key3 = Root(array, l);
				if (!dictionary2.TryGetValue(key3, out var value3))
				{
					value3 = (dictionary2[key3] = new List<int>());
				}
				value3.Add(l);
			}
			List<List<int>> list3 = new List<List<int>>();
			foreach (List<int> value4 in dictionary2.Values)
			{
				if (value4.Count >= minimum)
				{
					list3.Add(value4);
				}
			}
			return list3;
		}
	}
	public static class ConfigSections
	{
		public static ConfigEntry<T> CopyIfMissing<T>(ConfigFile config, ConfigEntry<T> source, string key, T defaultValue, ConfigDescription description, bool copySourceIfMissing = true)
		{
			string section = ((ConfigEntryBase)source).Definition.Section;
			ConfigEntry<T> result = default(ConfigEntry<T>);
			if (config.TryGetEntry<T>(section, key, ref result))
			{
				return result;
			}
			bool saveOnConfigSet = config.SaveOnConfigSet;
			config.SaveOnConfigSet = false;
			try
			{
				ConfigEntry<string> val = config.Bind<string>(section, key, "", (ConfigDescription)null);
				string value = val.Value;
				config.Remove(((ConfigEntryBase)val).Definition);
				ConfigEntry<T> val2 = config.Bind<T>(section, key, defaultValue, description);
				if (!string.IsNullOrEmpty(value))
				{
					((ConfigEntryBase)val2).SetSerializedValue(value);
				}
				else if (copySourceIfMissing)
				{
					((ConfigEntryBase)val2).SetSerializedValue(((ConfigEntryBase)source).GetSerializedValue());
				}
				return val2;
			}
			finally
			{
				config.SaveOnConfigSet = saveOnConfigSet;
			}
		}

		public static ConfigEntry<T> Bind<T>(ConfigFile config, string oldSection, string section, string key, T defaultValue, ConfigDescription description)
		{
			if (oldSection == section)
			{
				return config.Bind<T>(section, key, defaultValue, description);
			}
			ConfigEntry<T> result = default(ConfigEntry<T>);
			if (config.TryGetEntry<T>(section, key, ref result))
			{
				return result;
			}
			bool saveOnConfigSet = config.SaveOnConfigSet;
			config.SaveOnConfigSet = false;
			try
			{
				ConfigEntry<T> val2 = default(ConfigEntry<T>);
				ConfigEntryBase val = (ConfigEntryBase)(config.TryGetEntry<T>(oldSection, key, ref val2) ? ((object)val2) : ((object)config.Bind<string>(oldSection, key, "", (ConfigDescription)null)));
				ConfigEntry<string> val3 = config.Bind<string>(section, key, "", (ConfigDescription)null);
				string text = (string.IsNullOrEmpty(val3.Value) ? val.GetSerializedValue() : val3.Value);
				config.Remove(val.Definition);
				config.Remove(((ConfigEntryBase)val3).Definition);
				ConfigEntry<T> val4 = config.Bind<T>(section, key, defaultValue, description);
				if (!string.IsNullOrEmpty(text))
				{
					((ConfigEntryBase)val4).SetSerializedValue(text);
				}
				return val4;
			}
			finally
			{
				config.SaveOnConfigSet = saveOnConfigSet;
			}
		}

		internal static string PreviousSection(string section, string key)
		{
			switch (section)
			{
			case "Minimap":
				switch (key)
				{
				default:
					return "Names";
				case "Minimap creature icons":
				case "Minimap creature icon size":
					return "Icons";
				case "Minimap":
					return "Maps";
				}
			case "Large map":
				switch (key)
				{
				default:
					return "Names";
				case "Creature icons":
				case "Large map creature icon size":
					return "Icons";
				case "Large map":
					return "Maps";
				}
			case "Sharing":
			case "Tools":
			case "Maps":
				return "General";
			case "Icons":
			case "Names":
				return "Display";
			case "Grouping":
				if (!(key == "Group creatures"))
				{
					return "General";
				}
				return "Creatures";
			default:
				return section;
			}
		}

		internal static string CurrentSection(string section, string key)
		{
			if (section == "Maps")
			{
				if (!(key == "Minimap"))
				{
					if (!(key == "Large map"))
					{
						return section;
					}
					return "Large map";
				}
				return "Minimap";
			}
			if (section == "Icons")
			{
				switch (key)
				{
				case "Minimap creature icons":
				case "Minimap creature icon size":
					return "Minimap";
				case "Creature icons":
				case "Large map creature icon size":
					return "Large map";
				}
			}
			if (section == "Names")
			{
				switch (key)
				{
				case "Hide minimap names":
				case "Minimap name distance":
					return "Minimap";
				case "Hide large map names":
					return "Large map";
				}
			}
			return section;
		}
	}
	public sealed class CreatureContour : BaseMeshEffect
	{
		private readonly List<UIVertex> original = new List<UIVertex>();

		private int thickness = 1;

		internal int Thickness
		{
			get
			{
				return thickness;
			}
			set
			{
				int num = Mathf.Clamp(value, 1, 4);
				if (num != thickness)
				{
					thickness = num;
					if ((Object)(object)((BaseMeshEffect)this).graphic != (Object)null)
					{
						((BaseMeshEffect)this).graphic.SetVerticesDirty();
					}
				}
			}
		}

		public override void ModifyMesh(VertexHelper mesh)
		{
			//IL_0044: 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)
			if (!((UIBehaviour)this).IsActive())
			{
				return;
			}
			original.Clear();
			mesh.GetUIVertexStream(original);
			if (original.Count != 0)
			{
				mesh.Clear();
				for (int i = 1; i <= thickness; i++)
				{
					Layer(mesh, i, new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue));
				}
				for (int j = 0; j < original.Count; j++)
				{
					mesh.AddVert(original[j]);
				}
				int num = mesh.currentVertCount - original.Count;
				for (int k = 0; k < original.Count; k += 3)
				{
					mesh.AddTriangle(num + k, num + k + 1, num + k + 2);
				}
			}
		}

		private void Layer(VertexHelper mesh, float radius, Color32 tint)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_006d: 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)
			//IL_0079: 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_0081: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			for (int i = 0; i < 8; i++)
			{
				float num = (float)i * (float)Math.PI / 4f;
				((Vector3)(ref val))..ctor(Mathf.Cos(num) * radius, Mathf.Sin(num) * radius, 0f);
				int currentVertCount = mesh.currentVertCount;
				for (int j = 0; j < original.Count; j++)
				{
					UIVertex val2 = original[j];
					ref Vector3 position = ref val2.position;
					position += val;
					val2.color = new Color32(tint.r, tint.g, tint.b, (byte)(tint.a * val2.color.a / 255));
					mesh.AddVert(val2);
				}
				for (int k = 0; k < original.Count; k += 3)
				{
					mesh.AddTriangle(currentVertCount + k, currentVertCount + k + 1, currentVertCount + k + 2);
				}
			}
		}
	}
	internal static class CreatureDisplay
	{
		internal static bool ShowHead(bool large, float distance, float zoom, float minimum, float nativeThreshold, bool iconsEnabled = true)
		{
			if (iconsEnabled)
			{
				if (large)
				{
					return MapLabelZoom.Visible(zoom, minimum, nativeThreshold);
				}
				return true;
			}
			return false;
		}

		internal static bool ShowNearbyName(float distance, float maximum = 30f)
		{
			return distance <= maximum;
		}
	}
	internal sealed class CreatureHoverName : IDisposable
	{
		private TextMeshProUGUI text;

		private void Hide()
		{
			if ((Object)(object)text != (Object)null && ((Component)text).gameObject.activeSelf)
			{
				((Component)text).gameObject.SetActive(false);
			}
		}

		internal void Apply(IEnumerable<MarkerRecord> records, Minimap map, Plugin host, Func<MarkerRecord, string> name)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0062: 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)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: 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_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0454: Unknown result type (might be due to invalid IL or missing references)
			//IL_046a: Unknown result type (might be due to invalid IL or missing references)
			//IL_046f: Unknown result type (might be due to invalid IL or missing references)
			//IL_040d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0422: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)map == (Object)null || (int)map.m_mode != 2 || !host.Enabled.Value || !host.LargeMap.Value || host.Window.Open)
			{
				Hide();
				return;
			}
			Canvas componentInParent = map.m_largeRoot.GetComponentInParent<Canvas>();
			Canvas val = ((componentInParent != null) ? componentInParent.rootCanvas : null);
			Camera val2 = (((Object)(object)val != (Object)null && (int)val.renderMode != 0) ? val.worldCamera : null);
			Vector2 val3 = Vector2.op_Implicit(ZInput.pointerPosition);
			if (!RectTransformUtility.RectangleContainsScreenPoint(((Graphic)map.m_mapImageLarge).rectTransform, val3, val2))
			{
				Hide();
				return;
			}
			MarkerRecord markerRecord = null;
			float num = float.MaxValue;
			Rect rect;
			foreach (MarkerRecord record in records)
			{
				if (record.entry != null && !((Object)(object)record.pin?.m_uiElement == (Object)null) && ((Component)record.pin.m_uiElement).gameObject.activeInHierarchy && !host.Tracking.HasGroupDetails(record))
				{
					float num2 = Vector2.Distance(val3, RectTransformUtility.WorldToScreenPoint(val2, ((Transform)record.pin.m_uiElement).position));
					rect = record.pin.m_uiElement.rect;
					float width = ((Rect)(ref rect)).width;
					rect = record.pin.m_uiElement.rect;
					float num3 = Mathf.Max(16f, Mathf.Max(width, ((Rect)(ref rect)).height) * 0.5f) * (((Object)(object)val != (Object)null) ? val.scaleFactor : 1f);
					if (num2 <= num3 && num2 < num)
					{
						num = num2;
						markerRecord = record;
					}
				}
			}
			if (markerRecord == null)
			{
				Hide();
				return;
			}
			if (markerRecord.largeNameShown)
			{
				PinNameData namePinData = markerRecord.pin.m_NamePinData;
				if (namePinData != null)
				{
					GameObject pinNameGameObject = namePinData.PinNameGameObject;
					if (((pinNameGameObject != null) ? new bool?(pinNameGameObject.activeInHierarchy) : ((bool?)null)) == true)
					{
						Hide();
						return;
					}
				}
			}
			if ((Object)(object)this.text != (Object)null && (Object)(object)((TMP_Text)this.text).transform.parent != (Object)(object)map.m_largeRoot.transform)
			{
				Object.Destroy((Object)(object)((Component)this.text).gameObject);
				this.text = null;
			}
			if ((Object)(object)this.text == (Object)null)
			{
				this.text = NativeMapText.Create("MapTrackerCreatureHoverName", map.m_largeRoot.transform, map);
				((TMP_Text)this.text).fontSize = 16f;
				((Graphic)this.text).color = Color.white;
				((TMP_Text)this.text).richText = false;
				((Graphic)this.text).raycastTarget = false;
				((TMP_Text)this.text).alignment = (TextAlignmentOptions)4098;
				((TMP_Text)this.text).textWrappingMode = (TextWrappingModes)0;
				((TMP_Text)this.text).overflowMode = (TextOverflowModes)1;
				RectTransform rectTransform = ((TMP_Text)this.text).rectTransform;
				RectTransform rectTransform2 = ((TMP_Text)this.text).rectTransform;
				Vector2 val4 = default(Vector2);
				((Vector2)(ref val4))..ctor(0.5f, 0.5f);
				rectTransform2.anchorMax = val4;
				rectTransform.anchorMin = val4;
				((TMP_Text)this.text).rectTransform.pivot = new Vector2(0.5f, 0f);
				((TMP_Text)this.text).rectTransform.sizeDelta = new Vector2(280f, 24f);
			}
			bool flag = NameTextStyle.Apply((TMP_Text)(object)this.text, markerRecord.entry.creature ? host.CreatureNameSize.Value : host.ObjectNameSize.Value, ellipsis: true);
			string text = name(markerRecord) + ((markerRecord.group != null) ? (" ×" + markerRecord.group.Count) : "");
			if (((TMP_Text)this.text).text != text)
			{
				((TMP_Text)this.text).text = text;
				flag = true;
			}
			if (flag)
			{
				((TMP_Text)this.text).rectTransform.sizeDelta = new Vector2(280f, Mathf.Max(24f, ((TMP_Text)this.text).GetPreferredValues(text).y + 4f));
			}
			Transform transform = map.m_largeRoot.transform;
			RectTransform val5 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Vector2 val6 = RectTransformUtility.WorldToScreenPoint(val2, ((Transform)markerRecord.pin.m_uiElement).position);
			ref float y = ref val6.y;
			float num4 = y;
			rect = markerRecord.pin.m_uiElement.rect;
			y = num4 + (((Rect)(ref rect)).height * 0.5f + 5f) * (((Object)(object)val != (Object)null) ? val.scaleFactor : 1f);
			Vector2 val7 = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val5, val6, val2, ref val7))
			{
				RectTransform rectTransform3 = ((TMP_Text)this.text).rectTransform;
				Vector2 val8 = val7;
				rect = val5.rect;
				rectTransform3.anchoredPosition = val8 - ((Rect)(ref rect)).center;
			}
			if (!((Component)this.text).gameObject.activeSelf)
			{
				((Component)this.text).gameObject.SetActive(true);
			}
		}

		public void Dispose()
		{
			if ((Object)(object)text != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)text).gameObject);
			}
			text = null;
		}
	}
	internal static class CreatureIconResolver
	{
		internal static Sprite Resolve(GameObject creature, string prefab)
		{
			string text;
			switch (prefab)
			{
			case "Greyling":
			{
				Sprite obj = TrophyItem("TrophyGreyling");
				if (obj == null)
				{
					obj = Trophy(creature);
					if (obj == null)
					{
						obj = TrophyItem("TrophyGreydwarf");
						if (obj == null)
						{
							ZNetScene instance = ZNetScene.instance;
							obj = Trophy((instance != null) ? instance.GetPrefab("Greydwarf") : null);
						}
					}
				}
				return obj;
			}
			case "Boar_piggy":
				text = "Boar";
				break;
			case "Wolf_cub":
				text = "Wolf";
				break;
			case "Asksvin_hatchling":
				text = "Asksvin";
				break;
			case "Lox_Calf":
				text = "Lox";
				break;
			default:
				return Trophy(creature) ?? TrophyItem("Trophy" + prefab) ?? CustomCreatureIcons.For(prefab);
			}
			object obj2 = CustomCreatureIcons.For(prefab);
			if (obj2 == null)
			{
				ZNetScene instance2 = ZNetScene.instance;
				obj2 = Trophy((instance2 != null) ? instance2.GetPrefab(text) : null) ?? TrophyItem("Trophy" + text) ?? Trophy(creature);
			}
			return (Sprite)obj2;
		}

		private static Sprite TrophyItem(string prefab)
		{
			ObjectDB instance = ObjectDB.instance;
			object obj = ((instance != null) ? instance.GetItemPrefab(prefab) : null);
			if (obj == null)
			{
				ZNetScene instance2 = ZNetScene.instance;
				obj = ((instance2 != null) ? instance2.GetPrefab(prefab) : null);
			}
			if (obj == null)
			{
				return null;
			}
			ItemDrop component = ((GameObject)obj).GetComponent<ItemDrop>();
			if (component == null)
			{
				return null;
			}
			return component.m_itemData.GetIcon();
		}

		private static Sprite Trophy(GameObject creature)
		{
			CharacterDrop val = (((Object)(object)creature != (Object)null) ? creature.GetComponent<CharacterDrop>() : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			foreach (Drop item in val.m_drops.Where((Drop d) => (Object)(object)d.m_prefab != (Object)null && ((Object)d.m_prefab).name.StartsWith("Trophy", StringComparison.OrdinalIgnoreCase)))
			{
				ItemDrop component = item.m_prefab.GetComponent<ItemDrop>();
				Sprite val2 = ((component != null) ? component.m_itemData.GetIcon() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
			return null;
		}
	}
	internal sealed class CreatureMapIcon
	{
		private RectTransform root;

		private CreatureContour contour;

		private Image head;

		private Sprite previousSprite;

		private float previousSize;

		private bool previousContrast;

		private int previousThickness;

		internal void Update(RectTransform parent, Sprite sprite, float size, bool visible, bool contrast, int thickness)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root != (Object)null && (Object)(object)((Transform)root).parent != (Object)(object)parent)
			{
				Object.Destroy((Object)(object)((Component)root).gameObject);
				root = null;
			}
			if (!visible || (Object)(object)sprite == (Object)null)
			{
				if ((Object)(object)root != (Object)null)
				{
					((Component)root).gameObject.SetActive(false);
				}
				return;
			}
			if ((Object)(object)root == (Object)null)
			{
				GameObject val = new GameObject("MapTrackerCreatureBadge", new Type[1] { typeof(RectTransform) });
				val.layer = ((Component)parent).gameObject.layer;
				val.transform.SetParent((Transform)(object)parent, false);
				root = (RectTransform)val.transform;
				Center(root);
				((Transform)root).SetAsFirstSibling();
				head = CreateImage("Head", root);
				head.preserveAspect = true;
				contour = ((Component)head).gameObject.AddComponent<CreatureContour>();
				previousSprite = null;
			}
			if (!((Component)root).gameObject.activeSelf || !((Object)(object)previousSprite == (Object)(object)sprite) || previousSize != size || previousContrast != contrast || previousThickness != thickness)
			{
				previousSprite = sprite;
				previousSize = size;
				previousContrast = contrast;
				previousThickness = thickness;
				((Component)root).gameObject.SetActive(true);
				root.anchoredPosition = Vector2.zero;
				root.sizeDelta = new Vector2(size, size);
				((Behaviour)contour).enabled = contrast;
				contour.Thickness = thickness;
				head.sprite = sprite;
				((Graphic)head).rectTransform.sizeDelta = new Vector2(size, size);
			}
		}

		private static Image CreateImage(string name, RectTransform parent)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			})
			{
				layer = ((Component)parent).gameObject.layer
			};
			val.transform.SetParent((Transform)(object)parent, false);
			Image component = val.GetComponent<Image>();
			((Graphic)component).raycastTarget = false;
			Center(((Graphic)component).rectTransform);
			return component;
		}

		private static void Center(RectTransform rect)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0022: 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)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 0.5f);
			rect.pivot = val;
			Vector2 anchorMin = (rect.anchorMax = val);
			rect.anchorMin = anchorMin;
			rect.anchoredPosition = Vector2.zero;
		}
	}
	internal struct CreatureNamePoint
	{
		internal float WorldX;

		internal float WorldZ;

		internal float ScreenX;

		internal float ScreenY;

		internal int Count;

		internal string Kind;
	}
	internal static class CreatureNameGroupMath
	{
		internal static List<List<int>> Build(List<CreatureNamePoint> names, int radius)
		{
			if (radius <= 0)
			{
				throw new ArgumentOutOfRangeException("radius");
			}
			List<ClusterPoint> list = new List<ClusterPoint>(names.Count);
			foreach (CreatureNamePoint name in names)
			{
				list.Add(new ClusterPoint
				{
					X = name.WorldX,
					Y = name.WorldZ,
					WorldX = name.WorldX,
					WorldZ = name.WorldZ,
					Kind = name.Kind
				});
			}
			return ClusterMath.BuildBounded(list, radius, 2, radius * 2, radius * 2);
		}

		internal static void Centre(List<CreatureNamePoint> points, out float x, out float y, out int count)
		{
			double num = 0.0;
			double num2 = 0.0;
			count = 0;
			foreach (CreatureNamePoint point in points)
			{
				int num3 = Math.Max(1, point.Count);
				count += num3;
				num += (double)(point.ScreenX * (float)num3);
				num2 += (double)(point.ScreenY * (float)num3);
			}
			x = ((count > 0) ? ((float)(num / (double)count)) : 0f);
			y = ((count > 0) ? ((float)(num2 / (double)count)) : 0f);
		}
	}
	internal sealed class CreatureNameGroups
	{
		private readonly List<MarkerRecord> eligible = new List<MarkerRecord>();

		private readonly HashSet<MarkerRecord> visible = new HashSet<MarkerRecord>();

		private readonly List<CreatureNamePoint> points = new List<CreatureNamePoint>();

		private readonly List<CreatureNamePoint> centrePoints = new List<CreatureNamePoint>();

		private List<List<MarkerRecord>> groups = new List<List<MarkerRecord>>();

		private float nextBuild;

		private float previousZoom;

		private int previousCount = -1;

		private int previousRadius;

		private MapMode previousMode;

		internal void Invalidate()
		{
			nextBuild = 0f;
			previousCount = -1;
		}

		internal void Reset()
		{
			Invalidate();
			groups.Clear();
			eligible.Clear();
			visible.Clear();
			points.Clear();
			centrePoints.Clear();
		}

		internal void Apply(IEnumerable<MarkerRecord> records, Minimap map, Plugin host)
		{
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Invalid comparison between Unknown and I4
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: 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_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			eligible.Clear();
			visible.Clear();
			foreach (MarkerRecord record in records)
			{
				record.nameGroupMembers = null;
				record.nameGroupFollower = false;
				if (host.GroupCreatureNames.Value)
				{
					CatalogEntry entry = record.entry;
					if (entry != null && entry.creature && !host.Tracking.Discoveries.IsNavigationTarget(record) && !((Object)(object)record.pin?.m_uiElement == (Object)null) && ((Component)record.pin.m_uiElement).gameObject.activeInHierarchy)
					{
						eligible.Add(record);
						visible.Add(record);
					}
				}
			}
			if (!host.GroupCreatureNames.Value || eligible.Count < 2)
			{
				Invalidate();
				return;
			}
			Canvas componentInParent = map.m_largeRoot.GetComponentInParent<Canvas>();
			Canvas val = ((componentInParent != null) ? componentInParent.rootCanvas : null);
			Camera val2 = (((Object)(object)val != (Object)null && (int)val.renderMode != 0) ? val.worldCamera : null);
			float num = (((int)map.m_mode == 2) ? map.LargeZoom : map.SmallZoom);
			if (Time.realtimeSinceStartup >= nextBuild || previousCount != eligible.Count || previousRadius != host.CreatureNameGroupRadius.Value || previousZoom != num || previousMode != map.m_mode)
			{
				points.Clear();
				foreach (MarkerRecord item in eligible)
				{
					points.Add(new CreatureNamePoint
					{
						WorldX = item.pin.m_pos.x,
						WorldZ = item.pin.m_pos.z,
						Kind = item.type + ":" + ((object)((Graphic)item.pin.m_iconElement).color/*cast due to .constrained prefix*/).ToString()
					});
				}
				groups = (from indices in CreatureNameGroupMath.Build(points, host.CreatureNameGroupRadius.Value)
					select indices.Select((int i) => eligible[i]).ToList()).ToList();
				previousCount = eligible.Count;
				previousRadius = host.CreatureNameGroupRadius.Value;
				previousMode = map.m_mode;
				previousZoom = num;
				nextBuild = Time.realtimeSinceStartup + 0.2f;
			}
			foreach (List<MarkerRecord> group in groups)
			{
				if (group.Any((MarkerRecord member) => !visible.Contains(member)))
				{
					nextBuild = 0f;
					continue;
				}
				centrePoints.Clear();
				foreach (MarkerRecord item2 in group)
				{
					Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val2, ((Transform)item2.pin.m_uiElement).position);
					centrePoints.Add(new CreatureNamePoint
					{
						ScreenX = val3.x,
						ScreenY = val3.y,
						Count = (item2.group?.Count ?? 1)
					});
				}
				CreatureNameGroupMath.Centre(centrePoints, out var x, out var y, out var count);
				MarkerRecord markerRecord = group[0];
				markerRecord.nameGroupMembers = group;
				markerRecord.nameGroupScreen = new Vector2(x, y);
				string text = host.Tracking.Name(markerRecord);
				if (markerRecord.nameGroupCaption == null || markerRecord.nameGroupBase != text || markerRecord.nameGroupCount != count)
				{
					markerRecord.nameGroupBase = text;
					markerRecord.nameGroupCount = count;
					markerRecord.nameGroupCaption = text + " ×" + count;
				}
				PinNameData namePinData = markerRecord.pin.m_NamePinData;
				TMP_Text val4 = ((namePinData != null) ? namePinData.PinNameText : null);
				if ((Object)(object)val4 != (Object)null && val4.text != markerRecord.nameGroupCaption)
				{
					val4.text = markerRecord.nameGroupCaption;
				}
				for (int num2 = 1; num2 < group.Count; num2++)
				{
					group[num2].nameGroupFollower = true;
				}
			}
		}
	}
	internal sealed class CreatureNearbyName : IDisposable
	{
		private TextMeshProUGUI text;

		private readonly NativeNameVisibility visibility = new NativeNameVisibility();

		private string previousName;

		private int previousFontSize;

		private bool reportedEmpty;

		private static readonly Stack<TextMeshProUGUI> pool = new Stack<TextMeshProUGUI>();

		internal static void ClearPool()
		{
			while (pool.Count > 0)
			{
				TextMeshProUGUI val = pool.Pop();
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
		}

		internal void Hide()
		{
			visibility.Apply(((Object)(object)text != (Object)null) ? ((Component)text).gameObject : null, visible: false);
		}

		internal void SetVisible(bool show)
		{
			visibility.Apply(((Object)(object)text != (Object)null) ? ((Component)text).gameObject : null, show);
		}

		internal void Show(RectTransform parent, Minimap map, string name, int fontSize, Vector2? center = null)
		{
			//IL_0211: 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)
			//IL_0121: 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_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: Unknown result type (might be due to invalid IL or missing references)
			RectTransform pinRootSmall = map.m_pinRootSmall;
			if ((Object)(object)text != (Object)null && (Object)(object)((TMP_Text)text).transform.parent != (Object)(object)pinRootSmall)
			{
				Dispose();
			}
			if ((Object)(object)text == (Object)null)
			{
				while (pool.Count > 0 && (Object)(object)text == (Object)null)
				{
					text = pool.Pop();
				}
				if ((Object)(object)text == (Object)null)
				{
					text = NativeMapText.Create("MapTrackerNearbyCreatureName", (Transform)(object)pinRootSmall, map);
				}
				else if ((Object)(object)((TMP_Text)text).transform.parent != (Object)(object)pinRootSmall)
				{
					((TMP_Text)text).transform.SetParent((Transform)(object)pinRootSmall, false);
				}
				previousName = null;
				reportedEmpty = false;
				((TMP_Text)text).fontSize = 13f;
				((Graphic)text).color = Color.white;
				((TMP_Text)text).richText = false;
				((Graphic)text).raycastTarget = false;
				((TMP_Text)text).enableAutoSizing = false;
				((TMP_Text)text).isOrthographic = true;
				((TMP_Text)text).margin = Vector4.zero;
				if ((Object)(object)((TMP_Text)text).font != (Object)null)
				{
					((TMP_Text)text).fontSharedMaterial = ((TMP_Asset)((TMP_Text)text).font).material;
				}
				((TMP_Text)text).alignment = (TextAlignmentOptions)4097;
				((TMP_Text)text).textWrappingMode = (TextWrappingModes)0;
				((TMP_Text)text).overflowMode = (TextOverflowModes)1;
				RectTransform rectTransform = ((TMP_Text)text).rectTransform;
				RectTransform rectTransform2 = ((TMP_Text)text).rectTransform;
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(0.5f, 0.5f);
				rectTransform2.anchorMax = val;
				rectTransform.anchorMin = val;
				((TMP_Text)text).rectTransform.pivot = new Vector2(0f, 0.5f);
				((TMP_Text)text).rectTransform.sizeDelta = new Vector2(120f, 18f);
			}
			Canvas componentInParent = ((Component)pinRootSmall).GetComponentInParent<Canvas>();
			Canvas val2 = ((componentInParent != null) ? componentInParent.rootCanvas : null);
			Camera val3 = (((Object)(object)val2 != (Object)null && (int)val2.renderMode != 0) ? val2.worldCamera : null);
			bool flag = NameTextStyle.Apply((TMP_Text)(object)text, fontSize, ellipsis: true);
			bool num = previousName != name || previousFontSize != fontSize || flag;
			if (num)
			{
				previousName = name;
				previousFontSize = fontSize;
				((TMP_Text)text).fontSize = fontSize;
				((TMP_Text)text).text = name;
				Vector2 preferredValues = ((TMP_Text)text).GetPreferredValues(name);
				((TMP_Text)text).rectTransform.sizeDelta = new Vector2(Mathf.Clamp(preferredValues.x + 4f, 4f, 120f), Mathf.Max(18f, preferredValues.y + 4f));
			}
			Rect rect;
			Vector2 val4;
			if (!center.HasValue)
			{
				rect = parent.rect;
				float num2 = ((Rect)(ref rect)).xMax + 3f;
				rect = parent.rect;
				val4 = RectTransformUtility.WorldToScreenPoint(val3, ((Transform)parent).TransformPoint(new Vector3(num2, ((Rect)(ref rect)).center.y, 0f)));
			}
			else
			{
				Vector2 value = center.Value;
				rect = ((TMP_Text)text).rectTransform.rect;
				val4 = value - new Vector2(((Rect)(ref rect)).width * 0.5f * (((Object)(object)val2 != (Object)null) ? val2.scaleFactor : 1f), 0f);
			}
			Vector2 val5 = val4;
			Vector2 val6 = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(pinRootSmall, val5, val3, ref val6))
			{
				((Transform)((TMP_Text)text).rectTransform).localPosition = new Vector3(val6.x, val6.y, 0f);
			}
			((Component)text).gameObject.SetActive(true);
			if (!num)
			{
				return;
			}
			((TMP_Text)text).ForceMeshUpdate(false, false);
			if (!reportedEmpty && !string.IsNullOrEmpty(name) && ((TMP_Text)text).textInfo.characterCount == 0)
			{
				reportedEmpty = true;
				Plugin instance = Plugin.Instance;
				if (instance != null)
				{
					TMP_FontAsset font = ((TMP_Text)text).font;
					instance.Report("Minimap creature name produced no glyphs: " + name + "; font=" + ((font != null) ? ((Object)font).name : null));
				}
			}
		}

		internal LabelBox Bounds(Camera camera)
		{
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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)
			//IL_002b: 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_0034: 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)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			RectTransform rectTransform = ((TMP_Text)text).rectTransform;
			Rect rect = rectTransform.rect;
			Vector2 val = RectTransformUtility.WorldToScreenPoint(camera, ((Transform)rectTransform).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).min)));
			rect = rectTransform.rect;
			Vector2 val2 = RectTransformUtility.WorldToScreenPoint(camera, ((Transform)rectTransform).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).max)));
			return new LabelBox(Mathf.Min(val.x, val2.x), Mathf.Min(val.y, val2.y), Mathf.Abs(val2.x - val.x), Mathf.Abs(val2.y - val.y));
		}

		internal void Move(Camera camera, Vector2 offset)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			LabelLeader.Move(((TMP_Text)text).rectTransform, camera, offset);
		}

		internal string RenderState(Camera camera)
		{
			if ((Object)(object)text == (Object)null)
			{
				return "label=not-created";
			}
			LabelBox labelBox = Bounds(camera);
			string[] obj = new string[20]
			{
				"labelActive=",
				((Component)text).gameObject.activeInHierarchy.ToString(),
				", chars=",
				((TMP_Text)text).textInfo.characterCount.ToString(),
				", meshVertices=",
				((((TMP_Text)text).textInfo.meshInfo.Length != 0) ? ((TMP_Text)text).textInfo.meshInfo[0].vertexCount : 0).ToString(),
				", culled=",
				text.canvasRenderer.cull.ToString(),
				", alpha=",
				text.canvasRenderer.GetInheritedAlpha().ToString("0.###", CultureInfo.InvariantCulture),
				", font=",
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null
			};
			TMP_FontAsset font = ((TMP_Text)text).font;
			obj[11] = ((font != null) ? ((Object)font).name : null);
			obj[12] = ", screen=";
			obj[13] = labelBox.X.ToString("0", CultureInfo.InvariantCulture);
			obj[14] = ",";
			obj[15] = labelBox.Y.ToString("0", CultureInfo.InvariantCulture);
			obj[16] = ",";
			obj[17] = labelBox.Width.ToString("0", CultureInfo.InvariantCulture);
			obj[18] = ",";
			obj[19] = labelBox.Height.ToString("0", CultureInfo.InvariantCulture);
			return string.Concat(obj);
		}

		public void Dispose()
		{
			visibility.Dispose();
			if ((Object)(object)text != (Object)null)
			{
				((Component)text).gameObject.SetActive(false);
				if (pool.Count < 128)
				{
					pool.Push(text);
				}
				else
				{
					Object.Destroy((Object)(object)((Component)text).gameObject);
				}
			}
			text = null;
			previousName = null;
		}
	}
	internal sealed class CreatureStars
	{
		private RectTransform root;

		private readonly RectTransform[] stars = (RectTransform[])(object)new RectTransform[2];

		private int previousCount = -1;

		private float previousSize;

		internal void Update(RectTransform parent, int count, float pointSize)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: 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_00f5: 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_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Expected O, but got Unknown
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			count = Mathf.Clamp(count, 0, 2);
			if ((Object)(object)root != (Object)null && (Object)(object)((Transform)root).parent != (Object)(object)parent)
			{
				Object.Destroy((Object)(object)((Component)root).gameObject);
				root = null;
			}
			if (count == 0)
			{
				if ((Object)(object)root != (Object)null)
				{
					((Component)root).gameObject.SetActive(false);
				}
				return;
			}
			if ((Object)(object)root == (Object)null)
			{
				GameObject val = new GameObject("MapTrackerStars", new Type[1] { typeof(RectTransform) });
				val.layer = ((Component)parent).gameObject.layer;
				val.transform.SetParent((Transform)(object)parent, false);
				root = (RectTransform)val.transform;
				previousCount = -1;
				RectTransform obj = root;
				RectTransform obj2 = root;
				RectTransform obj3 = root;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(0.5f, 0.5f);
				obj3.pivot = val2;
				Vector2 anchorMin = (obj2.anchorMax = val2);
				obj.anchorMin = anchorMin;
				for (int i = 0; i < stars.Length; i++)
				{
					GameObject val4 = new GameObject("Star" + (i + 1), new Type[3]
					{
						typeof(RectTransform),
						typeof(CanvasRenderer),
						typeof(StarGraphic)
					});
					val4.layer = ((Component)parent).gameObject.layer;
					val4.transform.SetParent((Transform)(object)root, false);
					stars[i] = (RectTransform)val4.transform;
					RectTransform obj4 = stars[i];
					RectTransform obj5 = stars[i];
					RectTransform obj6 = stars[i];
					((Vector2)(ref val2))..ctor(0.5f, 0.5f);
					obj6.pivot = val2;
					anchorMin = (obj5.anchorMax = val2);
					obj4.anchorMin = anchorMin;
					StarGraphic component = val4.GetComponent<StarGraphic>();
					((Graphic)component).color = new Color(1f, 0.83f, 0.25f);
					((Graphic)component).raycastTarget = false;
				}
			}
			if (!((Component)root).gameObject.activeSelf || previousCount != count || previousSize != pointSize)
			{
				previousCount = count;
				previousSize = pointSize;
				((Component)root).gameObject.SetActive(true);
				float num = Mathf.Clamp(pointSize * 0.65f, 4f, 8f);
				root.anchoredPosition = new Vector2(0f, pointSize * 0.5f + num * 0.5f + 1.5f);
				root.sizeDelta = new Vector2((float)count * (num + 1.5f), num);
				for (int j = 0; j < stars.Length; j++)
				{
					((Component)stars[j]).gameObject.SetActive(j < count);
					stars[j].sizeDelta = new Vector2(num, num);
					stars[j].anchoredPosition = new Vector2(((float)j - (float)(count - 1) * 0.5f) * (num + 1.5f), 0f);
				}
			}
		}
	}
	public sealed class StarGraphic : MaskableGraphic
	{
		protected override void OnPopulateMesh(VertexHelper mesh)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_0092: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			mesh.Clear();
			Rect pixelAdjustedRect = ((Graphic)this).GetPixelAdjustedRect();
			Vector2 center = ((Rect)(ref pixelAdjustedRect)).center;
			float num = Mathf.Min(((Rect)(ref pixelAdjustedRect)).width, ((Rect)(ref pixelAdjustedRect)).height) * 0.5f;
			mesh.AddVert(Vector2.op_Implicit(center), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
			for (int i = 0; i < 10; i++)
			{
				float num2 = (float)Math.PI / 2f + (float)i * (float)Math.PI / 5f;
				float num3 = ((i % 2 == 0) ? num : (num * 0.45f));
				mesh.AddVert(Vector2.op_Implicit(center + new Vector2(Mathf.Cos(num2), Mathf.Sin(num2)) * num3), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
			}
			for (int j = 0; j < 10; j++)
			{
				mesh.AddTriangle(0, j + 1, (j + 1) % 10 + 1);
			}
		}
	}
	internal static class CustomCreatureIcons
	{
		private static readonly Dictionary<string, Sprite> icons = new Dictionary<string, Sprite>();

		private static MethodInfo decode;

		internal static Sprite For(string prefab)
		{
			switch (prefab)
			{
			case "Bat":
			case "Bat_Swamp":
				return Load("bat");
			case "Hen":
				return Load("hen");
			case "Chicken":
				return Load("chick");
			case "Boar_piggy":
				return Load("boar-young");
			case "Wolf_cub":
				return Load("wolf-cub");
			case "Asksvin_hatchling":
				return Load("asksvin-hatchling");
			case "Lox_Calf":
				return Load("lox-calf");
			default:
				return null;
			}
		}

		private static Sprite Load(string name)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_014e: 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)
			if (icons.TryGetValue(name, out var value))
			{
				return value;
			}
			Texture2D val = null;
			try
			{
				using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MapTracker.CreatureIcons." + name + ".png"))
				{
					if (stream == null)
					{
						throw new FileNotFoundException("Embedded creature icon is missing: " + name);
					}
					using MemoryStream memoryStream = new MemoryStream();
					stream.CopyTo(memoryStream);
					val = new Texture2D(2, 2, (TextureFormat)4, false);
					((Object)val).name = "MapTracker_" + name;
					((Texture)val).filterMode = (FilterMode)1;
					((Texture)val).wrapMode = (TextureWrapMode)1;
					if (decode == null)
					{
						decode = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule", throwOnError: true).GetMethod("LoadImage", new Type[3]
						{
							typeof(Texture2D),
							typeof(byte[]),
							typeof(bool)
						});
					}
					if (decode == null || !(bool)decode.Invoke(null, new object[3]
					{
						val,
						memoryStream.ToArray(),
						true
					}))
					{
						throw new InvalidDataException("Invalid creature icon: " + name);
					}
				}
				Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
				((Object)val2).name = "MapTracker_" + name;
				icons[name] = val2;
				return val2;
			}
			catch (Exception e)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
				icons[name] = null;
				Plugin.Instance?.Report("Could not load creature icon " + name, e);
				return null;
			}
		}

		internal static void Dispose()
		{
			foreach (Sprite value in icons.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value.texture);
					Object.Destroy((Object)(object)value);
				}
			}
			icons.Clear();
		}
	}
	public static class DataJson
	{
		private sealed class PositionConverter : JsonConverter
		{
			public override bool CanConvert(Type type)
			{
				return type == typeof(Vector3);
			}

			public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
			{
				//IL_0001: 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_0019: 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_0047: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = (Vector3)value;
				writer.WriteStartObject();
				writer.WritePropertyName("x");
				writer.WriteValue(val.x);
				writer.WritePropertyName("y");
				writer.WriteValue(val.y);
				writer.WritePropertyName("z");
				writer.WriteValue(val.z);
				writer.WriteEndObject();
			}

			public override object ReadJson(JsonReader reader, Type type, object existing, JsonSerializer serializer)
			{
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				JObject val = JObject.Load(reader);
				return (object)new Vector3(((float?)val["x"]).GetValueOrDefault(), ((float?)val["y"]).GetValueOrDefault(), ((float?)val["z"]).GetValueOrDefault());
			}
		}

		private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
		{
			TypeNameHandling = (TypeNameHandling)0,
			MaxDepth = 32,
			Converters = { (JsonConverter)(object)new PositionConverter() }
		};

		private static readonly JsonSerializerSettings NetworkSettings = new JsonSerializerSettings
		{
			TypeNameHandling = (TypeNameHandling)0,
			MaxDepth = 32,
			DefaultValueHandling = (DefaultValueHandling)1,
			Converters = { (JsonConverter)(object)new PositionConverter() }
		};

		public static string Write(object value, bool pretty = false)
		{
			return JsonConvert.SerializeObject(value, (Formatting)(pretty ? 1 : 0), Settings);
		}

		internal static void WriteTo(TextWriter output, object value)
		{
			//IL_0001: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			JsonTextWriter val = new JsonTextWriter(output)
			{
				Formatting = (Formatting)1,
				CloseOutput = false
			};
			try
			{
				JsonSerializer.Create(Settings).Serialize((JsonWriter)(object)val, value);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		internal static string WriteNetwork(object value)
		{
			return JsonConvert.SerializeObject(value, (Formatting)0, NetworkSettings);
		}

		public static T Read<T>(string json)
		{
			return JsonConvert.DeserializeObject<T>(json, Settings);
		}
	}
	public static class DefaultSettings
	{
		private static readonly Dictionary<string, Dictionary<string, string>> settings = Load();

		private static Dictionary<string, Dictionary<string, string>> Load()
		{
			using Stream stream = typeof(DefaultSettings).Assembly.GetManifestResourceStream("MapTracker.DefaultSettings.json");
			using StreamReader streamReader = new StreamReader(stream);
			return DataJson.Read<Dictionary<string, Dictionary<string, string>>>(streamReader.ReadToEnd());
		}

		public static T Value<T>(string section, string key, T fallback)
		{
			if (!settings.TryGetValue(section, out var value) || !value.TryGetValue(key, out var value2))
			{
				string text = ConfigSections.PreviousSection(section, key);
				if (text == section || !settings.TryGetValue(text, out value) || !value.TryGetValue(key, out value2))
				{
					return fallback;
				}
			}
			if (typeof(T) == typeof(bool))
			{
				return (T)(object)bool.Parse(value2);
			}
			if (typeof(T) == typeof(int))
			{
				return (T)(object)int.Parse(value2, CultureInfo.InvariantCulture);
			}
			throw new NotSupportedException("Unsupported initial setting type: " + typeof(T).Name);
		}

		public static ConfigEntry<T> Bind<T>(ConfigFile config, string oldSection, string section, string key, T fallback, ConfigDescription description)
		{
			return ConfigSections.Bind(config, oldSection, section, key, Value(section, key, fallback), description);
		}
	}
	internal static class DiscoveryNotification
	{
		internal static bool Allowed(MarkerRecord record, bool allDungeons, bool selectedType)
		{
			if (record.entry != null && !record.dynamic && !record.shared && !record.imported && !record.collected)
			{
				return (allDungeons && record.entry.dungeon) || selectedType;
			}
			return false;
		}
	}
	internal sealed class DiscoveryNotificationFeed
	{
		private readonly Queue<MarkerRecord> pending = new Queue<MarkerRecord>();

		private readonly HashSet<string> ids = new HashSet<string>(StringComparer.Ordinal);

		private float remaining;

		private float lastTick;

		private bool wasVisible;

		internal MarkerRecord Current { get; private set; }

		internal bool Enqueue(MarkerRecord item)
		{
			if (item == null || pending.Count >= 64 || !ids.Add(item.id))
			{
				return false;
			}
			pending.Enqueue(item);
			return true;
		}

		internal void Tick(float now, bool visible)
		{
			if (visible && wasVisible && Current != null)
			{
				remaining -= Math.Max(0f, now - lastTick);
			}
			lastTick = now;
			wasVisible = visible;
			if (visible)
			{
				if (Current != null && remaining <= 0f)
				{
					ids.Remove(Current.id);
					Current = null;
				}
				if (Current == null && pending.Count > 0)
				{
					Current = pending.Dequeue();
					remaining = 4f;
				}
			}
		}

		internal void Clear()
		{
			pending.Clear();
			ids.Clear();
			Current = null;
			remaining = (lastTick = 0f);
			wasVisible = false;
		}
	}
	internal sealed class DiscoveryNotificationHud : IDisposable
	{
		private RectTransform root;

		private TextMeshProUGUI title;

		private TextMeshProUGUI caption;

		private MarkerRecord previous;

		private readonly NavigationTargetIcon icon = new NavigationTargetIcon();

		internal static bool CanShow(Minimap map, bool enabled)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			Player localPlayer = Player.m_localPlayer;
			if (enabled && (Object)(object)localPlayer != (Object)null && (Object)(object)Hud.instance != (Object)null && Hud.instance.IsVisible() && (Object)(object)map != (Object)null && (int)map.m_mode != 2 && !Menu.IsVisible() && !InventoryGui.IsVisible() && !Console.IsVisible() && !TextInput.IsVisible() && !((Character)localPlayer).IsDead() && !((Character)localPlayer).IsTeleporting())
			{
				return !((Character)localPlayer).InCutscene();
			}
			return false;
		}

		internal void Apply(Minimap map, MarkerRecord item, bool visible)
		{
			//IL_00c2: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			if (!visible || item == null)
			{
				if ((Object)(object)root != (Object)null)
				{
					((Component)root).gameObject.SetActive(false);
				}
				return;
			}
			Hud instance = Hud.instance;
			Transform obj = ((instance != null) ? instance.m_rootObject.transform : null);
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if (!((Object)(object)val == (Object)null))
			{
				if ((Object)(object)root != (Object)null && (Object)(object)((Transform)root).parent != (Object)(object)val)
				{
					Dispose();
				}
				if ((Object)(object)root == (Object)null)
				{
					Create(val, map);
				}
				if (!((Component)root).gameObject.activeSelf)
				{
					((Component)root).gameObject.SetActive(true);
				}
				((Transform)root).SetAsLastSibling();
				Rect rect = val.rect;
				float num = Mathf.Min(420f, Mathf.Max(220f, ((Rect)(ref rect)).width - 32f));
				if (root.sizeDelta.x != num)
				{
					root.sizeDelta = new Vector2(num, 88f);
					((TMP_Text)title).rectTransform.sizeDelta = new Vector2(num - 96f, 24f);
					((TMP_Text)caption).rectTransform.sizeDelta = new Vector2(num - 96f, 42f);
				}
				if (previous != item)
				{
					previous = item;
					((TMP_Text)caption).text = item.nameCache ?? "";
				}
				icon.Apply(root, map, item, new Vector2((0f - num) * 0.5f + 40f, -44f), 44f);
			}
		}

		private void Create(RectTransform parent, Minimap map)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("MapTrackerDiscoveryNotification", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(DiscoveryNotificationPanel)
			});
			val.layer = ((Component)parent).gameObject.layer;
			root = (RectTransform)val.transform;
			((Transform)root).SetParent((Transform)(object)parent, false);
			RectTransform obj = root;
			RectTransform obj2 = root;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 1f);
			obj2.anchorMax = val2;
			obj.anchorMin = val2;
			root.pivot = new Vector2(0.5f, 1f);
			root.sizeDelta = new Vector2(420f, 88f);
			root.anchoredPosition = new Vector2(0f, -195f);
			((Graphic)val.GetComponent<DiscoveryNotificationPanel>()).raycastTarget = false;
			title = NativeMapText.Create("NewDiscovery", (Transform)(object)root, map);
			caption = NativeMapText.Create("ObjectName", (Transform)(object)root, map);
			Configure(title, 17, new Color(1f, 0.83f, 0.33f), -12f, 24f);
			Configure(caption, 20, Color.white, -36f, 42f);
			((TMP_Text)title).text = "New discovery";
		}

		private static void Configure(TextMeshProUGUI text, int size, Color tint, float y, float height)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0068: 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_0080: 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)
			((TMP_Text)text).fontSize = size;
			((TMP_Text)text).enableAutoSizing = false;
			((Graphic)text).color = tint;
			((TMP_Text)text).richText = false;
			((Graphic)text).raycastTarget = false;
			((TMP_Text)text).alignment = (TextAlignmentOptions)257;
			((TMP_Text)text).textWrappingMode = (TextWrappingModes)1;
			(