Decompiled source of PortalPicker v1.2.3

PortalPicker.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("PortalPicker")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.3.0")]
[assembly: AssemblyInformationalVersion("1.2.3")]
[assembly: AssemblyProduct("PortalPicker")]
[assembly: AssemblyTitle("PortalPicker")]
[assembly: AssemblyVersion("1.2.3.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 PortalPicker
{
	internal sealed class ColorField : MaskableGraphic
	{
		private const int Cells = 12;

		internal bool HueStrip;

		private float hue;

		internal float Hue
		{
			get
			{
				return hue;
			}
			set
			{
				if (!Mathf.Approximately(hue, value))
				{
					hue = value;
					((Graphic)this).SetVerticesDirty();
				}
			}
		}

		protected override void OnPopulateMesh(VertexHelper vh)
		{
			//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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_013f: 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)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			vh.Clear();
			Rect pixelAdjustedRect = ((Graphic)this).GetPixelAdjustedRect();
			if (HueStrip)
			{
				for (int i = 0; i < 6; i++)
				{
					Color val = Color.HSVToRGB((float)i / 6f, 1f, 1f);
					Color val2 = Color.HSVToRGB((float)((i + 1) % 6) / 6f, 1f, 1f);
					float num = ((Rect)(ref pixelAdjustedRect)).yMax - ((Rect)(ref pixelAdjustedRect)).height * (float)i / 6f;
					float num2 = ((Rect)(ref pixelAdjustedRect)).yMax - ((Rect)(ref pixelAdjustedRect)).height * (float)(i + 1) / 6f;
					Quad(vh, new Rect(((Rect)(ref pixelAdjustedRect)).xMin, num2, ((Rect)(ref pixelAdjustedRect)).width, num - num2), val2, val2, val, val);
				}
				return;
			}
			Rect rect = default(Rect);
			for (int j = 0; j < 12; j++)
			{
				for (int k = 0; k < 12; k++)
				{
					float num3 = (float)k / 12f;
					float num4 = (float)(k + 1) / 12f;
					float num5 = (float)j / 12f;
					float num6 = (float)(j + 1) / 12f;
					((Rect)(ref rect))..ctor(((Rect)(ref pixelAdjustedRect)).xMin + ((Rect)(ref pixelAdjustedRect)).width * num3, ((Rect)(ref pixelAdjustedRect)).yMin + ((Rect)(ref pixelAdjustedRect)).height * num5, ((Rect)(ref pixelAdjustedRect)).width / 12f, ((Rect)(ref pixelAdjustedRect)).height / 12f);
					Quad(vh, rect, Color.HSVToRGB(hue, num3, num5), Color.HSVToRGB(hue, num4, num5), Color.HSVToRGB(hue, num3, num6), Color.HSVToRGB(hue, num4, num6));
				}
			}
		}

		private static void Quad(VertexHelper vh, Rect rect, Color lb, Color rb, Color lt, Color rt)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003f: 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)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_0079: 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_0099: 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)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			int currentVertCount = vh.currentVertCount;
			vh.AddVert(new Vector3(((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMin), Color32.op_Implicit(lb), Vector4.op_Implicit(Vector2.zero));
			vh.AddVert(new Vector3(((Rect)(ref rect)).xMax, ((Rect)(ref rect)).yMin), Color32.op_Implicit(rb), Vector4.op_Implicit(Vector2.zero));
			vh.AddVert(new Vector3(((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMax), Color32.op_Implicit(lt), Vector4.op_Implicit(Vector2.zero));
			vh.AddVert(new Vector3(((Rect)(ref rect)).xMax, ((Rect)(ref rect)).yMax), Color32.op_Implicit(rt), Vector4.op_Implicit(Vector2.zero));
			vh.AddTriangle(currentVertCount, currentVertCount + 2, currentVertCount + 3);
			vh.AddTriangle(currentVertCount, currentVertCount + 3, currentVertCount + 1);
		}
	}
	internal enum IconCategory
	{
		All,
		Places,
		Trophies,
		Gear,
		Food,
		Resources,
		Buildings
	}
	internal sealed class IconDef
	{
		public string Key;

		public IconCategory Category;

		public string Token;

		public Sprite Source;

		public bool Plain;

		public string Search;

		public string Title => Localization.instance.Localize(Token);
	}
	internal static class IconLibrary
	{
		private static readonly string[] SkipPlaces = new string[6] { "player", "ping", "shout", "randevent", "eventarea", "checked" };

		private static readonly string[] FirstPlaces = new string[14]
		{
			"mapicon_house", "mapicon_fire", "mapicon_hammer", "mapicon_trader", "mapicon_boss", "mapicon_death", "mapicon_bogwitch_camp", "mapicon_mysteriousplace2", "mapicon_start", "mapicon_memorialplace",
			"mapicon_bed", "mapicon_hildir_wagon", "mapicon_portal", "mapicon_pin"
		};

		internal static readonly string[] DefaultRecent = new string[8] { "map:mapicon_house", "map:mapicon_fire", "map:mapicon_hammer", "map:mapicon_trader", "map:mapicon_boss", "map:mapicon_start", "item:TrophyEikthyr", "item:PickaxeIron" };

		private static readonly Dictionary<string, IconDef> byKey = new Dictionary<string, IconDef>();

		private static readonly List<IconDef> all = new List<IconDef>();

		private static readonly Dictionary<Sprite, Sprite> converted = new Dictionary<Sprite, Sprite>();

		private static bool built;

		internal static bool Ready
		{
			get
			{
				if ((Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items.Count > 0)
				{
					return (Object)(object)Minimap.instance != (Object)null;
				}
				return false;
			}
		}

		internal static IReadOnlyList<IconDef> All
		{
			get
			{
				EnsureBuilt();
				return all;
			}
		}

		internal static void Reset()
		{
			built = false;
			byKey.Clear();
			all.Clear();
		}

		internal static IconDef Find(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return null;
			}
			EnsureBuilt();
			if (!byKey.TryGetValue(key, out var value))
			{
				return null;
			}
			return value;
		}

		internal static Sprite SpriteOf(string key)
		{
			IconDef iconDef = Find(key);
			if (iconDef == null)
			{
				return null;
			}
			return Display(iconDef);
		}

		internal static bool IsCheap(IconDef def)
		{
			if (!def.Plain && !((Object)(object)def.Source == (Object)null))
			{
				return converted.ContainsKey(def.Source);
			}
			return true;
		}

		internal static Sprite Display(IconDef def)
		{
			if (def.Plain || (Object)(object)def.Source == (Object)null)
			{
				return def.Source;
			}
			if (!converted.TryGetValue(def.Source, out var value))
			{
				value = IconArt.Monochrome(def.Source) ?? def.Source;
				converted[def.Source] = value;
			}
			return value;
		}

		internal static Sprite PortalPin()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Invalid comparison between Unknown and I4
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			Sprite val = SpriteOf("map:mapicon_portal");
			if ((Object)(object)val == (Object)null && (Object)(object)Minimap.instance != (Object)null)
			{
				foreach (SpriteData icon in Minimap.instance.m_icons)
				{
					if ((int)icon.m_name == 6)
					{
						val = icon.m_icon;
					}
				}
			}
			return val;
		}

		private static void EnsureBuilt()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			if (built || !Ready)
			{
				return;
			}
			built = true;
			HashSet<Sprite> hashSet = new HashSet<Sprite>();
			List<IconDef> list = new List<IconDef>();
			foreach (SpriteData icon in Minimap.instance.m_icons)
			{
				AddPlace(list, hashSet, icon.m_icon);
			}
			foreach (LocationSpriteData locationIcon in Minimap.instance.m_locationIcons)
			{
				AddPlace(list, hashSet, locationIcon.m_icon);
			}
			list.Sort(delegate(IconDef a, IconDef b)
			{
				int num = Array.IndexOf(FirstPlaces, ((Object)a.Source).name);
				int num2 = Array.IndexOf(FirstPlaces, ((Object)b.Source).name);
				if (num < 0)
				{
					num = 1000;
				}
				if (num2 < 0)
				{
					num2 = 1000;
				}
				return (num == num2) ? string.CompareOrdinal(((Object)a.Source).name, ((Object)b.Source).name) : num.CompareTo(num2);
			});
			List<IconDef> list2 = new List<IconDef>();
			List<IconDef> list3 = new List<IconDef>();
			HashSet<PieceTable> hashSet2 = new HashSet<PieceTable>();
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				ItemDrop val = (((Object)(object)item != (Object)null) ? item.GetComponent<ItemDrop>() : null);
				if (!((Object)(object)val == (Object)null) && val.m_itemData?.m_shared != null)
				{
					SharedData shared = val.m_itemData.m_shared;
					if ((Object)(object)shared.m_buildPieces != (Object)null)
					{
						hashSet2.Add(shared.m_buildPieces);
					}
					Sprite val2 = ((shared.m_icons != null && shared.m_icons.Length != 0) ? shared.m_icons[0] : null);
					if (!((Object)(object)val2 == (Object)null) && !Junk(((Object)item).name) && hashSet.Add(val2))
					{
						list2.Add(new IconDef
						{
							Key = "item:" + ((Object)item).name,
							Category = CategoryOf(shared.m_itemType),
							Token = shared.m_name,
							Source = val2
						});
					}
				}
			}
			foreach (PieceTable item2 in hashSet2)
			{
				foreach (GameObject piece in item2.m_pieces)
				{
					Piece val3 = (((Object)(object)piece != (Object)null) ? piece.GetComponent<Piece>() : null);
					if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.m_icon == (Object)null) && !Junk(((Object)piece).name) && hashSet.Add(val3.m_icon))
					{
						list3.Add(new IconDef
						{
							Key = "piece:" + ((Object)piece).name,
							Category = IconCategory.Buildings,
							Token = val3.m_name,
							Source = val3.m_icon
						});
					}
				}
			}
			foreach (IconDef item3 in list)
			{
				Register(item3);
			}
			list2.AddRange(list3);
			foreach (IconDef item4 in list2)
			{
				item4.Search = item4.Title.ToLowerInvariant();
			}
			list2.Sort((IconDef a, IconDef b) => (a.Category == b.Category) ? string.Compare(a.Search, b.Search, StringComparison.CurrentCulture) : a.Category.CompareTo(b.Category));
			foreach (IconDef item5 in list2)
			{
				Register(item5);
			}
			PortalPickerPlugin.Log.LogInfo((object)$"Portal icons: {list.Count} map marks, {list2.Count - list3.Count} items, {list3.Count} pieces");
		}

		private static void AddPlace(List<IconDef> places, HashSet<Sprite> seen, Sprite sprite)
		{
			if ((Object)(object)sprite == (Object)null || !seen.Add(sprite))
			{
				return;
			}
			string text = ((Object)sprite).name ?? "";
			string[] skipPlaces = SkipPlaces;
			foreach (string value in skipPlaces)
			{
				if (text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return;
				}
			}
			string text2 = (text.StartsWith("mapicon_") ? text.Substring(8) : text);
			IconDef iconDef = new IconDef
			{
				Key = "map:" + text,
				Category = IconCategory.Places,
				Token = "$q8pp_icon_" + text2,
				Source = sprite,
				Plain = true
			};
			if (iconDef.Title.StartsWith("["))
			{
				iconDef.Token = text2.Replace('_', ' ');
			}
			iconDef.Search = iconDef.Title.ToLowerInvariant();
			places.Add(iconDef);
		}

		private static void Register(IconDef def)
		{
			if (!byKey.ContainsKey(def.Key))
			{
				byKey.Add(def.Key, def);
				all.Add(def);
			}
		}

		private static bool Junk(string prefab)
		{
			string text = prefab.ToLowerInvariant();
			if (!text.Contains("cheat") && !text.Contains("debug") && !text.EndsWith("_old"))
			{
				return text.Contains("test");
			}
			return true;
		}

		private static IconCategory CategoryOf(ItemType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			if ((int)type <= 2)
			{
				if ((int)type <= 1)
				{
					goto IL_0023;
				}
				if ((int)type == 2)
				{
					return IconCategory.Food;
				}
			}
			else
			{
				if ((int)type == 13)
				{
					return IconCategory.Trophies;
				}
				if ((int)type == 16 || (int)type == 21)
				{
					goto IL_0023;
				}
			}
			return IconCategory.Gear;
			IL_0023:
			return IconCategory.Resources;
		}
	}
	internal static class IconArt
	{
		private const int Pad = 2;

		internal static Sprite Monochrome(Sprite source)
		{
			//IL_0008: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_0095: 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_00a9: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: 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_0130: 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_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: 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_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Expected O, but got Unknown
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Texture2D texture = source.texture;
				Rect textureRect = source.textureRect;
				int num = Mathf.RoundToInt(((Rect)(ref textureRect)).width);
				int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).height);
				if ((Object)(object)texture == (Object)null || num <= 0 || num2 <= 0)
				{
					return null;
				}
				RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)0);
				RenderTexture active = RenderTexture.active;
				Color32[] pixels;
				try
				{
					Graphics.Blit((Texture)(object)texture, temporary);
					RenderTexture.active = temporary;
					Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false);
					val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0);
					val.Apply(false);
					pixels = val.GetPixels32();
					Object.Destroy((Object)val);
				}
				finally
				{
					RenderTexture.active = active;
					RenderTexture.ReleaseTemporary(temporary);
				}
				int num3 = num + 4;
				int num4 = num2 + 4;
				float[] array = new float[num3 * num4];
				float[] array2 = new float[num3 * num4];
				for (int i = 0; i < num2; i++)
				{
					for (int j = 0; j < num; j++)
					{
						Color32 val2 = pixels[i * num + j];
						int num5 = (i + 2) * num3 + j + 2;
						array[num5] = (float)(int)val2.a / 255f;
						float num6 = (0.299f * (float)(int)val2.r + 0.587f * (float)(int)val2.g + 0.114f * (float)(int)val2.b) / 255f;
						array2[num5] = Mathf.Min(1f, 0.47f + 0.75f * num6);
					}
				}
				Color32[] array3 = (Color32[])(object)new Color32[num3 * num4];
				for (int k = 0; k < num4; k++)
				{
					for (int l = 0; l < num3; l++)
					{
						float num7 = 0f;
						for (int m = -2; m <= 2; m++)
						{
							int num8 = k + m;
							if (num8 < 0 || num8 >= num4)
							{
								continue;
							}
							for (int n = -2; n <= 2; n++)
							{
								int num9 = l + n;
								if (num9 >= 0 && num9 < num3 && array[num8 * num3 + num9] > num7)
								{
									num7 = array[num8 * num3 + num9];
								}
							}
						}
						int num10 = k * num3 + l;
						float num11 = array[num10];
						float num12 = num11 + num7 * (1f - num11);
						byte b = (byte)Mathf.RoundToInt(Mathf.Clamp01((num12 > 0f) ? ((array2[num10] * num11 + 0.086f * num7 * (1f - num11)) / num12) : 0f) * 255f);
						array3[num10] = new Color32(b, b, b, (byte)Mathf.RoundToInt(Mathf.Clamp01(num12) * 255f));
					}
				}
				Texture2D val3 = new Texture2D(num3, num4, (TextureFormat)4, false)
				{
					wrapMode = (TextureWrapMode)1,
					filterMode = (FilterMode)1,
					name = "q8pp_" + ((Object)source).name
				};
				val3.SetPixels32(array3);
				val3.Apply(false, true);
				Sprite obj = Sprite.Create(val3, new Rect(0f, 0f, (float)num3, (float)num4), new Vector2(0.5f, 0.5f), 100f);
				((Object)obj).name = "q8pp_" + ((Object)source).name;
				return obj;
			}
			catch (Exception ex)
			{
				PortalPickerPlugin.Log.LogWarning((object)("Icon " + ((Object)source).name + " kept in colour: " + ex.Message));
				return null;
			}
		}
	}
	internal static class MapPins
	{
		private sealed class Mark
		{
			public ZDOID Id;

			public string Name;

			public Vector3 Pos;

			public string Icon;

			public int Color;

			public string Owner;

			public bool Public;
		}

		private const string SnapshotKey = "q8pp_portals";

		private const int SnapshotFormat = 2;

		private static readonly Dictionary<PinData, Mark> pins = new Dictionary<PinData, Mark>();

		private static readonly Dictionary<PinData, Image> badges = new Dictionary<PinData, Image>();

		private static Minimap pinsOn;

		private static object shownItem;

		private static string shownSnapshot;

		private static int shownVersion = -1;

		private static bool faulted;

		private static bool linked;

		private static Func<ItemData> held;

		private static Func<Minimap, Vector3, bool> isDrawn;

		private static RectTransform tip;

		private static TextMeshProUGUI tipText;

		private static Mark tipMark;

		internal static void Reset()
		{
			pins.Clear();
			badges.Clear();
			pinsOn = null;
			shownItem = null;
			shownSnapshot = null;
			shownVersion = -1;
			tip = null;
			tipText = null;
			tipMark = null;
			faulted = false;
		}

		internal static bool LinkParchment(Harmony harmony)
		{
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			Type type = AccessTools.TypeByName("ParchmentMap.MapSession");
			MethodInfo methodInfo = ((type != null) ? AccessTools.PropertyGetter(type, "Held") : null);
			MethodInfo methodInfo2 = ((type != null) ? AccessTools.Method(type, "IsDrawn", new Type[2]
			{
				typeof(Minimap),
				typeof(Vector3)
			}, (Type[])null) : null);
			MethodInfo methodInfo3 = ((type != null) ? AccessTools.Method(type, "UseTable", new Type[3]
			{
				typeof(MapTable),
				typeof(Humanoid),
				typeof(bool)
			}, (Type[])null) : null);
			if (methodInfo == null || methodInfo2 == null || methodInfo3 == null)
			{
				return false;
			}
			held = (Func<ItemData>)Delegate.CreateDelegate(typeof(Func<ItemData>), methodInfo);
			isDrawn = (Func<Minimap, Vector3, bool>)Delegate.CreateDelegate(typeof(Func<Minimap, Vector3, bool>), methodInfo2);
			harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(MapPins), "UseTablePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			linked = true;
			return true;
		}

		internal static void Update()
		{
			if (faulted)
			{
				return;
			}
			try
			{
				UpdateCore();
			}
			catch (Exception ex)
			{
				faulted = true;
				PortalPickerPlugin.Log.LogError((object)("Portal marks on the map are switched off until you re-enter the world: " + ex));
			}
		}

		internal static void Colorize(Minimap minimap)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)minimap != (Object)(object)pinsOn)
			{
				return;
			}
			foreach (KeyValuePair<PinData, Mark> pin in pins)
			{
				PinData key = pin.Key;
				if ((Object)(object)key.m_iconElement != (Object)null)
				{
					((Graphic)key.m_iconElement).color = PortalMeta.ColorOf(pin.Value.Color);
				}
				if ((Object)(object)key.m_uiElement != (Object)null && (!badges.TryGetValue(key, out var value) || (Object)(object)value == (Object)null || (Object)(object)((Component)value).transform.parent != (Object)(object)key.m_uiElement))
				{
					badges[key] = AddBadge(key.m_uiElement);
				}
			}
		}

		private static Image AddBadge(RectTransform pinElement)
		{
			//IL_000b: 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_003b: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			Image obj = UiKit.Picture("q8pp_badge", (Transform)(object)pinElement, UiKit.PortalBadgeSprite, Color.white);
			RectTransform rectTransform = ((Graphic)obj).rectTransform;
			rectTransform.anchorMin = new Vector2(-0.07f, -0.07f);
			rectTransform.anchorMax = new Vector2(0.46f, 0.46f);
			rectTransform.offsetMin = Vector2.zero;
			rectTransform.offsetMax = Vector2.zero;
			return obj;
		}

		private static void UseTablePostfix(bool __result)
		{
			//IL_0054: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (!__result || !PortalList.Received || (Object)(object)Minimap.instance == (Object)null)
			{
				return;
			}
			try
			{
				ItemData val = held();
				if (val == null)
				{
					return;
				}
				List<Mark> list = new List<Mark>();
				foreach (PortalList.Entry entry in PortalList.Entries)
				{
					if (isDrawn(Minimap.instance, entry.Position))
					{
						list.Add(new Mark
						{
							Id = entry.Id,
							Name = PortalHover.CleanName(entry.Name),
							Pos = entry.Position,
							Icon = (entry.Icon ?? ""),
							Color = entry.Color,
							Owner = (entry.OwnerName ?? ""),
							Public = PortalMeta.IsPublic(entry.OwnerId)
						});
					}
				}
				val.m_customData["q8pp_portals"] = Serialize(list);
				PortalPickerPlugin.Log.LogInfo((object)$"Cartography table: {list.Count} of {PortalList.Entries.Count} portals are on the parchment");
			}
			catch (Exception ex)
			{
				PortalPickerPlugin.Log.LogWarning((object)("Could not write portals onto the parchment: " + ex.Message));
			}
		}

		private static void UpdateCore()
		{
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if ((Object)(object)instance != (Object)(object)pinsOn)
			{
				pins.Clear();
				badges.Clear();
				pinsOn = instance;
				shownItem = null;
				shownSnapshot = null;
				shownVersion = -1;
			}
			if (linked)
			{
				ItemData val = (((Object)(object)Player.m_localPlayer != (Object)null) ? held() : null);
				string value = null;
				val?.m_customData.TryGetValue("q8pp_portals", out value);
				if (val != shownItem || !string.Equals(value, shownSnapshot) || shownVersion < 0)
				{
					shownItem = val;
					shownSnapshot = value;
					shownVersion = 0;
					Rebuild(instance, Parse(value));
				}
			}
			else if (PortalList.Version != shownVersion)
			{
				shownVersion = PortalList.Version;
				List<Mark> list = new List<Mark>();
				foreach (PortalList.Entry entry in PortalList.Entries)
				{
					list.Add(new Mark
					{
						Id = entry.Id,
						Name = PortalHover.CleanName(entry.Name),
						Pos = entry.Position,
						Icon = (entry.Icon ?? ""),
						Color = entry.Color,
						Owner = (entry.OwnerName ?? ""),
						Public = PortalMeta.IsPublic(entry.OwnerId)
					});
				}
				Rebuild(instance, list);
			}
			UpdateTooltip(instance);
		}

		private static void Rebuild(Minimap minimap, List<Mark> marks)
		{
			//IL_0065: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			foreach (PinData key in pins.Keys)
			{
				minimap.RemovePin(key);
			}
			pins.Clear();
			badges.Clear();
			Sprite val = null;
			foreach (Mark mark in marks)
			{
				PinData val2 = minimap.AddPin(mark.Pos, (PinType)6, mark.Name, false, false, 0L, default(PlatformUserID));
				Sprite val3 = IconLibrary.SpriteOf(mark.Icon);
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = val ?? (val = IconLibrary.PortalPin());
				}
				if ((Object)(object)val3 != (Object)null)
				{
					val2.m_icon = val3;
				}
				pins[val2] = mark;
			}
		}

		private static void UpdateTooltip(Minimap minimap)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Expected O, but got Unknown
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			Mark mark = null;
			if ((int)minimap.m_mode == 2 && (Object)(object)minimap.m_largeRoot != (Object)null && minimap.m_largeRoot.activeInHierarchy)
			{
				Vector3 pointerPosition = ZInput.pointerPosition;
				foreach (KeyValuePair<PinData, Mark> pin in pins)
				{
					RectTransform uiElement = pin.Key.m_uiElement;
					if ((Object)(object)uiElement != (Object)null && ((Component)uiElement).gameObject.activeInHierarchy && RectTransformUtility.RectangleContainsScreenPoint(uiElement, Vector2.op_Implicit(pointerPosition), CameraOf((Transform)(object)uiElement)))
					{
						mark = pin.Value;
						break;
					}
				}
			}
			if (mark == null)
			{
				if ((Object)(object)tip != (Object)null)
				{
					((Component)tip).gameObject.SetActive(false);
				}
				tipMark = null;
				return;
			}
			if ((Object)(object)tip == (Object)null)
			{
				BuildTooltip(minimap.m_largeRoot.transform);
			}
			if (mark != tipMark)
			{
				tipMark = mark;
				string text = ((mark.Name.Length > 0) ? Localization.instance.Localize("$q8pp_header").Replace("{0}", mark.Name) : Localization.instance.Localize("$q8pp_header_unnamed"));
				string text2 = "<b>" + text + "</b>";
				if (mark.Public)
				{
					text2 = text2 + "\n<size=85%><b><color=#96BEEB>" + Localization.instance.Localize("$q8pp_public_portal") + "</color></b></size>";
				}
				else if (mark.Owner.Length > 0)
				{
					text2 = text2 + "\n<size=85%><color=#BFBFBF>" + Localization.instance.Localize("$q8pp_owned_by") + " </color><b><color=#96BEEB>" + mark.Owner + "</color></b></size>";
				}
				((TMP_Text)tipText).text = text2;
				Vector2 preferredValues = ((TMP_Text)tipText).GetPreferredValues(text2);
				tip.sizeDelta = new Vector2(preferredValues.x + 22f, preferredValues.y + 14f);
			}
			RectTransform val = (RectTransform)((Transform)tip).parent;
			Vector2 val2 = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val, Vector2.op_Implicit(ZInput.pointerPosition), CameraOf((Transform)(object)val), ref val2))
			{
				tip.anchoredPosition = val2 + new Vector2(18f, -14f);
			}
			((Component)tip).gameObject.SetActive(true);
			((Transform)tip).SetAsLastSibling();
		}

		private static void BuildTooltip(Transform parent)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = UiKit.Rect("q8pp_maptip", parent);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			val.anchorMax = val2;
			val.anchorMin = val2;
			val.pivot = new Vector2(0f, 1f);
			((Component)val).gameObject.AddComponent<CanvasRenderer>();
			Image obj = ((Component)val).gameObject.AddComponent<Image>();
			obj.sprite = UiKit.PanelSprite;
			obj.type = (Type)1;
			((Graphic)obj).raycastTarget = false;
			tipText = UiKit.Label("text", (Transform)(object)val, 16f, UiKit.Text, (TextAlignmentOptions)4097);
			RectTransform rectTransform = ((TMP_Text)tipText).rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			rectTransform.offsetMin = new Vector2(11f, 7f);
			rectTransform.offsetMax = new Vector2(-11f, -7f);
			tip = val;
		}

		private static Camera CameraOf(Transform element)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Canvas componentInParent = ((Component)element).GetComponentInParent<Canvas>();
			if (!((Object)(object)componentInParent == (Object)null) && (int)componentInParent.renderMode != 0)
			{
				return componentInParent.worldCamera;
			}
			return null;
		}

		private static string Serialize(List<Mark> marks)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_002c: 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)
			ZPackage val = new ZPackage();
			val.Write(2);
			val.Write(marks.Count);
			foreach (Mark mark in marks)
			{
				val.Write(mark.Id);
				val.Write(mark.Name);
				val.Write(mark.Pos);
				val.Write(mark.Icon);
				val.Write(mark.Color);
				val.Write(mark.Owner);
				val.Write(mark.Public);
			}
			return val.GetBase64();
		}

		private static List<Mark> Parse(string snapshot)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//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)
			List<Mark> list = new List<Mark>();
			if (string.IsNullOrEmpty(snapshot))
			{
				return list;
			}
			try
			{
				ZPackage val = new ZPackage(snapshot);
				int num = val.ReadInt();
				if (num != 1 && num != 2)
				{
					return list;
				}
				int num2 = val.ReadInt();
				for (int i = 0; i < num2; i++)
				{
					list.Add(new Mark
					{
						Id = val.ReadZDOID(),
						Name = val.ReadString(),
						Pos = val.ReadVector3(),
						Icon = val.ReadString(),
						Color = PortalMeta.NormalizeColor(val.ReadInt()),
						Owner = val.ReadString(),
						Public = (num >= 2 && val.ReadBool())
					});
				}
			}
			catch (Exception ex)
			{
				PortalPickerPlugin.Log.LogWarning((object)("Portals on this parchment cannot be read: " + ex.Message));
				list.Clear();
			}
			return list;
		}
	}
	[HarmonyPatch(typeof(Game), "Start")]
	internal static class GameStartPatch
	{
		private static void Postfix()
		{
			PlayerNames.OnGameStart();
			PortalList.OnGameStart();
			PortalHover.OnGameStart();
			IconLibrary.Reset();
			WheelHud.Reset();
			PortalPanel.Reset();
			MapPins.Reset();
		}
	}
	[HarmonyPatch(typeof(ZNet), "Shutdown")]
	internal static class ShutdownPatch
	{
		private static void Prefix()
		{
			PlayerNames.Flush();
		}
	}
	[HarmonyPatch(typeof(Game), "ConnectPortals")]
	internal static class NoPairingPatch
	{
		private static bool Prefix()
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(TeleportWorldTrigger), "OnTriggerEnter")]
	internal static class NoWalkInPatch
	{
		private static bool Prefix()
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "Awake")]
	internal static class PortalAwakePatch
	{
		private static void Postfix(ZNetView ___m_nview)
		{
			if ((Object)(object)___m_nview != (Object)null && ___m_nview.GetZDO() != null)
			{
				PortalMeta.Register(___m_nview);
			}
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "GetHoverText")]
	internal static class HoverTextPatch
	{
		private static bool Prefix(ZNetView ___m_nview, ref string __result)
		{
			ZDO val = (((Object)(object)___m_nview != (Object)null) ? ___m_nview.GetZDO() : null);
			__result = ((WheelHud.Working || val == null) ? " " : PortalHover.FallbackText(val));
			return false;
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "Interact")]
	internal static class InteractPatch
	{
		private static bool Prefix(TeleportWorld __instance, ZNetView ___m_nview, Humanoid human, bool hold, bool alt, ref bool __result)
		{
			ZDO val = (((Object)(object)___m_nview != (Object)null) ? ___m_nview.GetZDO() : null);
			if (hold || val == null)
			{
				__result = false;
			}
			else if (alt)
			{
				__result = PortalHover.Configure(__instance, human);
			}
			else
			{
				__result = PortalHover.Teleport(__instance, val, (Player)(object)((human is Player) ? human : null));
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "HaveTarget")]
	internal static class HaveTargetPatch
	{
		private static bool Prefix(ZNetView ___m_nview, ref bool __result)
		{
			__result = PortalHover.HasTargets(___m_nview);
			return false;
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "TargetFound")]
	internal static class TargetFoundPatch
	{
		private static bool Prefix(ZNetView ___m_nview, ref bool __result)
		{
			__result = PortalHover.HasTargets(___m_nview);
			return false;
		}
	}
	[HarmonyPatch(typeof(Minimap), "UpdatePins")]
	internal static class PinColorPatch
	{
		private static void Postfix(Minimap __instance)
		{
			MapPins.Colorize(__instance);
		}
	}
	[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
	internal static class CameraZoomPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo wheel = AccessTools.Method(typeof(ZInput), "GetMouseScrollWheel", (Type[])null, (Type[])null);
			MethodInfo ours = AccessTools.Method(typeof(PortalHover), "CameraScrollWheel", (Type[])null, (Type[])null);
			int replaced = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, wheel))
				{
					instruction.operand = ours;
					replaced++;
				}
				yield return instruction;
			}
			if (replaced == 0)
			{
				PortalPickerPlugin.Log.LogWarning((object)"Camera zoom by the wheel not found: the wheel will also zoom while choosing a portal");
			}
		}
	}
	[HarmonyPatch(typeof(HotkeyBar), "Update")]
	internal static class HotbarPatch
	{
		private static bool Prefix()
		{
			if (ZInput.IsGamepadActive())
			{
				return !PortalHover.ListOpen();
			}
			return true;
		}
	}
	internal static class PlayerNames
	{
		private const string Folder = "portalpicker";

		private const float SaveDelay = 10f;

		private static readonly Dictionary<long, string> names = new Dictionary<long, string>();

		private static string path;

		private static long world;

		private static bool dirty;

		private static float saveAt;

		internal static IReadOnlyDictionary<long, string> All => names;

		internal static void OnGameStart()
		{
			names.Clear();
			path = null;
			world = 0L;
			dirty = false;
		}

		internal static string NameOf(long id)
		{
			if (id == 0L || !names.TryGetValue(id, out var value))
			{
				return "";
			}
			return value;
		}

		internal static void Update()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			EnsureLoaded();
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				if (peer != null && !((ZDOID)(ref peer.m_characterID)).IsNone())
				{
					ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID);
					if (zDO != null)
					{
						Learn(zDO.GetLong(ZDOVars.s_playerID, 0L), zDO.GetString(ZDOVars.s_playerName, ""));
					}
				}
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				Learn(localPlayer.GetPlayerID(), localPlayer.GetPlayerName());
			}
			if (dirty && Time.time >= saveAt)
			{
				Save();
			}
		}

		internal static void Flush()
		{
			if (dirty)
			{
				Save();
			}
		}

		private static void Learn(long id, string name)
		{
			name = Clean(name);
			if (id != 0L && name.Length != 0 && !(name == "...") && (!names.TryGetValue(id, out var value) || value != name))
			{
				names[id] = name;
				if (!dirty)
				{
					saveAt = Time.time + 10f;
				}
				dirty = true;
			}
		}

		private static string Clean(string name)
		{
			return (name ?? "").Replace('\t', ' ').Replace('\r', ' ').Replace('\n', ' ')
				.Trim();
		}

		private static void LearnFromWorld()
		{
			if (!(AccessTools.Field(typeof(ZDOMan), "m_objectsByID")?.GetValue(ZDOMan.instance) is Dictionary<ZDOID, ZDO> dictionary))
			{
				PortalPickerPlugin.Log.LogWarning((object)"Player names: the world's objects are not reachable, names come only from players who join");
				return;
			}
			int count = names.Count;
			foreach (ZDO value in dictionary.Values)
			{
				string text = value.GetString(ZDOVars.s_ownerName, "");
				if (text.Length > 0)
				{
					LearnIfUnknown(value.GetLong(ZDOVars.s_owner, 0L), text);
				}
				string text2 = value.GetString(ZDOVars.s_creatorName, "");
				if (text2.Length > 0)
				{
					LearnIfUnknown(value.GetLong(ZDOVars.s_creator, 0L), text2);
				}
			}
			PortalPickerPlugin.Log.LogInfo((object)$"Player names: {names.Count - count} more from beds, wards and tombstones, {names.Count} known");
		}

		private static void LearnIfUnknown(long id, string name)
		{
			name = Clean(name);
			if (id != 0L && name.Length != 0 && !(name == "...") && !names.ContainsKey(id))
			{
				names[id] = name;
				if (!dirty)
				{
					saveAt = Time.time + 10f;
				}
				dirty = true;
			}
		}

		private static void EnsureLoaded()
		{
			long worldUID = ZNet.instance.GetWorldUID();
			if (PlayerNames.path != null && world == worldUID)
			{
				return;
			}
			names.Clear();
			dirty = false;
			world = worldUID;
			try
			{
				string path = Path.Combine(Utils.GetSaveDataPath((FileSource)2), "portalpicker");
				Directory.CreateDirectory(path);
				PlayerNames.path = Path.Combine(path, SafeName(ZNet.instance.GetWorldName()) + "." + worldUID.ToString("X") + ".players");
				if (File.Exists(PlayerNames.path))
				{
					string[] array = File.ReadAllLines(PlayerNames.path, Encoding.UTF8);
					foreach (string text in array)
					{
						int num = text.IndexOf('\t');
						if (num > 0 && long.TryParse(text.Substring(0, num), out var result) && result != 0L)
						{
							string text2 = Clean(text.Substring(num + 1));
							if (text2.Length > 0)
							{
								names[result] = text2;
							}
						}
					}
				}
				PortalPickerPlugin.Log.LogInfo((object)$"Player names: {PlayerNames.path}, {names.Count} known");
			}
			catch (Exception ex)
			{
				PortalPickerPlugin.Log.LogWarning((object)("Player names are kept only until the server stops: " + ex.Message));
				PlayerNames.path = "";
			}
			try
			{
				LearnFromWorld();
			}
			catch (Exception ex2)
			{
				PortalPickerPlugin.Log.LogWarning((object)("Player names from the world failed: " + ex2.Message));
			}
		}

		private static void Save()
		{
			dirty = false;
			if (string.IsNullOrEmpty(path))
			{
				return;
			}
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				foreach (KeyValuePair<long, string> name in names)
				{
					stringBuilder.Append(name.Key).Append('\t').Append(name.Value)
						.Append('\n');
				}
				string sourceFileName = path + ".tmp";
				File.WriteAllText(sourceFileName, stringBuilder.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
				if (File.Exists(path))
				{
					File.Delete(path);
				}
				File.Move(sourceFileName, path);
			}
			catch (Exception ex)
			{
				PortalPickerPlugin.Log.LogWarning((object)("Could not save player names: " + ex.Message));
			}
		}

		private static string SafeName(string name)
		{
			StringBuilder stringBuilder = new StringBuilder();
			string text = name ?? "world";
			foreach (char c in text)
			{
				stringBuilder.Append((char.IsLetterOrDigit(c) || c == '-' || c == '_') ? c : '_');
			}
			if (stringBuilder.Length <= 0)
			{
				return "world";
			}
			return stringBuilder.ToString();
		}
	}
	[BepInPlugin("qua8ion.valheim.portalpicker", "PortalPicker", "1.2.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInIncompatibility("yay.spikehimself.xportal")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class PortalPickerPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "qua8ion.valheim.portalpicker";

		public const string PluginName = "PortalPicker";

		public const string PluginVersion = "1.2.3";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> ShowDistance;

		internal static ConfigEntry<int> NameLength;

		internal static ConfigEntry<string> RecentIcons;

		internal static ConfigEntry<string> RecentColors;

		private void Awake()
		{
			//IL_002a: 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_0037: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_009d: 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_00af: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			//IL_00e1: 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_00f3: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ShowDistance = ((BaseUnityPlugin)this).Config.Bind<bool>("Rules", "ShowDistance", true, new ConfigDescription("Show in the list how far each portal is from the one you are looking at.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			NameLength = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "NameLength", 30, new ConfigDescription("Longest portal name you can type (the game's own limit is 10).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 60), Array.Empty<object>()));
			RecentIcons = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "RecentIcons", "", new ConfigDescription("Icons you gave portals lately, newest first (filled by the game).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				Browsable = false
			} }));
			RecentColors = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "RecentColors", "", new ConfigDescription("Your own colours you gave portals lately, RRGGBB, newest first (filled by the game).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				Browsable = false
			} }));
			AddLocalization();
			Harmony val = new Harmony("qua8ion.valheim.portalpicker");
			val.PatchAll(typeof(PortalPickerPlugin).Assembly);
			if (MapPins.LinkParchment(val))
			{
				Log.LogInfo((object)"ParchmentMap found: portals appear on a parchment at a cartography table");
			}
		}

		private void Update()
		{
			PortalList.Update();
			if (!GUIManager.IsHeadless())
			{
				PortalHover.Update();
				PortalPanel.Update();
				MapPins.Update();
			}
		}

		private void LateUpdate()
		{
			if (!GUIManager.IsHeadless())
			{
				WheelHud.LateUpdate();
			}
		}

		private static void AddLocalization()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{ "q8pp_header", "Portal \"{0}\"" },
				{ "q8pp_header_unnamed", "Portal without a name" },
				{ "q8pp_owned_by", "owned by" },
				{ "q8pp_unnamed", "no name" },
				{ "q8pp_unknown_owner", "unknown" },
				{ "q8pp_public", "public" },
				{ "q8pp_public_portal", "public portal" },
				{ "q8pp_owner_public", "— public, no owner —" },
				{ "q8pp_none", "No other portals yet" },
				{ "q8pp_loading", "Waiting for the list of portals" },
				{ "q8pp_go", "Travel" },
				{ "q8pp_choose", "Choose" },
				{ "q8pp_wheel", "Wheel" },
				{ "q8pp_m", "m" },
				{ "q8pp_km", "km" },
				{ "q8pp_decimal", "." },
				{ "q8pp_panel_title", "Portal" },
				{ "q8pp_label_name", "Name" },
				{ "q8pp_label_owner", "Owner" },
				{ "q8pp_label_icon", "Icon" },
				{ "q8pp_label_color", "Colour" },
				{ "q8pp_quick", "quick" },
				{ "q8pp_own_palette", "own palette" },
				{ "q8pp_palette_title", "Palette" },
				{ "q8pp_label_code", "Colour code" },
				{ "q8pp_label_recent_colors", "Recent" },
				{ "q8pp_recent_colors_click", "click to use it at once" },
				{ "q8pp_recent_colors_empty", "colours you choose will appear here" },
				{ "q8pp_palette_mouse", "square and strip with the mouse" },
				{ "q8pp_label_preview", "In the list" },
				{ "q8pp_label_favorite", "Favourite" },
				{ "q8pp_favorite_note", "only yours: the wheel at this portal starts on the portal you choose here" },
				{ "q8pp_no_favorite", "— none —" },
				{ "q8pp_ward_favorite_only", "someone else's ward: only your favourite can be changed" },
				{ "q8pp_keys_save", "save" },
				{ "q8pp_keys_cancel", "cancel" },
				{ "q8pp_recent", "recent" },
				{ "q8pp_all_icons", "all icons" },
				{ "q8pp_all_title", "All icons" },
				{ "q8pp_search", "search by name" },
				{ "q8pp_save", "Save" },
				{ "q8pp_cancel", "Cancel" },
				{ "q8pp_mouse_rest", "the rest with the mouse" },
				{ "q8pp_pick", "click to choose" },
				{ "q8pp_back", "Back" },
				{ "q8pp_tab_all", "All" },
				{ "q8pp_tab_places", "Places" },
				{ "q8pp_tab_trophies", "Trophies" },
				{ "q8pp_tab_gear", "Gear" },
				{ "q8pp_tab_food", "Food" },
				{ "q8pp_tab_resources", "Resources" },
				{ "q8pp_tab_buildings", "Buildings" },
				{ "q8pp_icon_house", "House" },
				{ "q8pp_icon_fire", "Campfire" },
				{ "q8pp_icon_hammer", "Hammer" },
				{ "q8pp_icon_trader", "Trader" },
				{ "q8pp_icon_boss", "Boss" },
				{ "q8pp_icon_death", "Skull" },
				{ "q8pp_icon_bogwitch_camp", "Cauldron" },
				{ "q8pp_icon_mysteriousplace2", "Cave" },
				{ "q8pp_icon_start", "Start" },
				{ "q8pp_icon_memorialplace", "Runestone" },
				{ "q8pp_icon_bed", "Bed" },
				{ "q8pp_icon_hildir_wagon", "Wagon" },
				{ "q8pp_icon_portal", "Portal" },
				{ "q8pp_icon_pin", "Dot" },
				{ "q8pp_icon_hildir", "Hildir" },
				{ "q8pp_icon_hildir_dress", "Shirt" },
				{ "q8pp_icon_hildir1", "Question" },
				{ "q8pp_icon_hildir2", "Question" },
				{ "q8pp_icon_hildir3", "Question" },
				{ "q8pp_icon_upgradestation", "Statue" }
			});
			text = "Russian";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				{ "q8pp_header", "Портал «{0}»" },
				{ "q8pp_header_unnamed", "Портал без названия" },
				{ "q8pp_owned_by", "принадлежит" },
				{ "q8pp_unnamed", "без названия" },
				{ "q8pp_unknown_owner", "неизвестно" },
				{ "q8pp_public", "общий" },
				{ "q8pp_public_portal", "общий портал" },
				{ "q8pp_owner_public", "— общий, без владельца —" },
				{ "q8pp_none", "Других порталов пока нет" },
				{ "q8pp_loading", "Жду список порталов" },
				{ "q8pp_go", "Переместиться" },
				{ "q8pp_choose", "Выбрать" },
				{ "q8pp_wheel", "Колесо" },
				{ "q8pp_m", "м" },
				{ "q8pp_km", "км" },
				{ "q8pp_decimal", "," },
				{ "q8pp_panel_title", "Портал" },
				{ "q8pp_label_name", "Название" },
				{ "q8pp_label_owner", "Владелец" },
				{ "q8pp_label_icon", "Значок" },
				{ "q8pp_label_color", "Цвет" },
				{ "q8pp_quick", "быстрые" },
				{ "q8pp_own_palette", "своя палитра" },
				{ "q8pp_palette_title", "Палитра" },
				{ "q8pp_label_code", "Код цвета" },
				{ "q8pp_label_recent_colors", "Последние" },
				{ "q8pp_recent_colors_click", "щелчок — сразу этот цвет" },
				{ "q8pp_recent_colors_empty", "здесь будут цвета, которые ты выбирал" },
				{ "q8pp_palette_mouse", "квадрат и полоса — мышью" },
				{ "q8pp_label_preview", "В списке" },
				{ "q8pp_label_favorite", "Избранный" },
				{ "q8pp_favorite_note", "только у тебя: колесо у этого портала сразу встаёт на выбранный здесь портал" },
				{ "q8pp_no_favorite", "— нет —" },
				{ "q8pp_ward_favorite_only", "чужой вард: менять можно только избранного" },
				{ "q8pp_keys_save", "сохранить" },
				{ "q8pp_keys_cancel", "отмена" },
				{ "q8pp_recent", "последние" },
				{ "q8pp_all_icons", "все значки" },
				{ "q8pp_all_title", "Все значки" },
				{ "q8pp_search", "поиск по названию" },
				{ "q8pp_save", "Сохранить" },
				{ "q8pp_cancel", "Отмена" },
				{ "q8pp_mouse_rest", "остальное — мышью" },
				{ "q8pp_pick", "щелчок — выбрать" },
				{ "q8pp_back", "Назад" },
				{ "q8pp_tab_all", "Все" },
				{ "q8pp_tab_places", "Места" },
				{ "q8pp_tab_trophies", "Трофеи" },
				{ "q8pp_tab_gear", "Орудия" },
				{ "q8pp_tab_food", "Еда" },
				{ "q8pp_tab_resources", "Ресурсы" },
				{ "q8pp_tab_buildings", "Постройки" },
				{ "q8pp_icon_house", "Дом" },
				{ "q8pp_icon_fire", "Костёр" },
				{ "q8pp_icon_hammer", "Молот" },
				{ "q8pp_icon_trader", "Торговец" },
				{ "q8pp_icon_boss", "Босс" },
				{ "q8pp_icon_death", "Череп" },
				{ "q8pp_icon_bogwitch_camp", "Котёл" },
				{ "q8pp_icon_mysteriousplace2", "Пещера" },
				{ "q8pp_icon_start", "Старт" },
				{ "q8pp_icon_memorialplace", "Рунный камень" },
				{ "q8pp_icon_bed", "Кровать" },
				{ "q8pp_icon_hildir_wagon", "Повозка" },
				{ "q8pp_icon_portal", "Портал" },
				{ "q8pp_icon_pin", "Точка" },
				{ "q8pp_icon_hildir", "Хильдир" },
				{ "q8pp_icon_hildir_dress", "Рубаха" },
				{ "q8pp_icon_hildir1", "Вопрос" },
				{ "q8pp_icon_hildir2", "Вопрос" },
				{ "q8pp_icon_hildir3", "Вопрос" },
				{ "q8pp_icon_upgradestation", "Статуя" }
			});
		}
	}
	internal static class PortalHover
	{
		internal struct Target
		{
			public PortalList.Entry Entry;

			public string Name;

			public float Distance;

			public int Group;

			public string Owner;

			public string Key;

			public bool Favorite;
		}

		private static string sourceKey;

		private static string choiceFor;

		private static string choice;

		private static string arrivedAt;

		private static string arrivedFrom;

		private static readonly List<Target> targets = new List<Target>();

		private static ZDOID targetsFor = ZDOID.None;

		private static int targetsVersion = -1;

		private static long targetsMe;

		private static int targetsMemory = -1;

		private static int openFrame = -1;

		private static TeleportWorld openPortal;

		private static ZDO openZdo;

		internal static IReadOnlyList<Target> Targets => targets;

		internal static void OnGameStart()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			sourceKey = (choiceFor = (choice = (arrivedAt = (arrivedFrom = null))));
			targetsFor = ZDOID.None;
			targetsVersion = -1;
			targetsMemory = -1;
			TripMemory.Reset();
		}

		internal static void Update()
		{
			if (!ListOpen())
			{
				return;
			}
			int num = 0;
			float mouseScrollWheel = ZInput.GetMouseScrollWheel();
			if (mouseScrollWheel > 0f)
			{
				num = -1;
			}
			else if (mouseScrollWheel < 0f)
			{
				num = 1;
			}
			if (ZInput.IsGamepadActive() && !ZInput.GetButton("JoyAltKeys"))
			{
				if (ZInput.GetButtonDown("JoyHotbarLeft"))
				{
					num = -1;
				}
				else if (ZInput.GetButtonDown("JoyHotbarRight"))
				{
					num = 1;
				}
			}
			if (num != 0 && targets.Count > 0)
			{
				int index = (SelectedIndex() + num + targets.Count) % targets.Count;
				choiceFor = sourceKey;
				choice = targets[index].Key;
			}
		}

		internal static bool Hovered(out TeleportWorld portal, out ZDO zdo)
		{
			Refresh();
			portal = openPortal;
			zdo = openZdo;
			if ((Object)(object)portal != (Object)null)
			{
				return zdo != null;
			}
			return false;
		}

		internal static bool ListOpen()
		{
			if (Hovered(out var _, out var zdo))
			{
				return PrepareTargets(zdo) > 0;
			}
			return false;
		}

		internal static float CameraScrollWheel()
		{
			if (!ListOpen())
			{
				return ZInput.GetMouseScrollWheel();
			}
			return 0f;
		}

		internal static bool HasTargets(ZNetView view)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			ZDO val = (((Object)(object)view != (Object)null) ? view.GetZDO() : null);
			if (val != null)
			{
				return PortalList.HasOtherThan(val.m_uid);
			}
			return false;
		}

		internal static int PrepareTargets(ZDO zdo)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			long num = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0);
			if (zdo.m_uid == targetsFor && PortalList.Version == targetsVersion && num == targetsMe && TripMemory.Version == targetsMemory)
			{
				return targets.Count;
			}
			sourceKey = TripMemory.KeyOf(zdo.GetPosition());
			string favorite = TripMemory.FavoriteOf(sourceKey);
			targetsFor = zdo.m_uid;
			targetsVersion = PortalList.Version;
			targetsMe = num;
			targetsMemory = TripMemory.Version;
			BuildTargets(zdo, num, targets);
			int num2 = ((favorite != null) ? targets.FindIndex((Target t) => t.Key == favorite) : (-1));
			if (num2 >= 0)
			{
				Target item = targets[num2];
				item.Favorite = true;
				targets.RemoveAt(num2);
				targets.Insert(0, item);
			}
			return targets.Count;
		}

		internal static List<Target> SortedTargets(ZDO zdo)
		{
			List<Target> list = new List<Target>();
			BuildTargets(zdo, ((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0, list);
			return list;
		}

		private static void BuildTargets(ZDO zdo, long me, List<Target> into)
		{
			//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_0025: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			into.Clear();
			Vector3 position = zdo.GetPosition();
			foreach (PortalList.Entry entry in PortalList.Entries)
			{
				if (!(entry.Id == zdo.m_uid))
				{
					into.Add(new Target
					{
						Entry = entry,
						Name = CleanName(entry.Name),
						Distance = Utils.DistanceXZ(position, entry.Position),
						Group = ((me == 0L || entry.OwnerId != me) ? (PortalMeta.IsPublic(entry.OwnerId) ? 1 : (string.IsNullOrEmpty(entry.OwnerName) ? 3 : 2)) : 0),
						Owner = (entry.OwnerName ?? ""),
						Key = TripMemory.KeyOf(entry.Position)
					});
				}
			}
			into.Sort(CompareTargets);
		}

		private static int CompareTargets(Target a, Target b)
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			if (a.Group != b.Group)
			{
				return a.Group.CompareTo(b.Group);
			}
			if (a.Group == 2)
			{
				int num = string.Compare(a.Owner, b.Owner, StringComparison.CurrentCultureIgnoreCase);
				if (num != 0)
				{
					return num;
				}
				if (a.Entry.OwnerId != b.Entry.OwnerId)
				{
					return a.Entry.OwnerId.CompareTo(b.Entry.OwnerId);
				}
			}
			bool flag = a.Name.Length > 0;
			bool flag2 = b.Name.Length > 0;
			if (flag != flag2)
			{
				if (!flag)
				{
					return 1;
				}
				return -1;
			}
			if (flag)
			{
				int num2 = string.Compare(a.Name, b.Name, StringComparison.CurrentCultureIgnoreCase);
				if (num2 != 0)
				{
					return num2;
				}
			}
			int num3 = a.Distance.CompareTo(b.Distance);
			if (num3 == 0)
			{
				return ((ZDOID)(ref a.Entry.Id)).CompareTo(b.Entry.Id);
			}
			return num3;
		}

		internal static int SelectedIndex()
		{
			string to = null;
			if (sourceKey != null)
			{
				if (choiceFor == sourceKey)
				{
					to = choice;
				}
				else
				{
					if (targets.Count > 0 && targets[0].Favorite)
					{
						return 0;
					}
					if (!TripMemory.TryGet(sourceKey, out to) && arrivedAt == sourceKey)
					{
						to = arrivedFrom;
					}
				}
			}
			if (to != null)
			{
				for (int i = 0; i < targets.Count; i++)
				{
					if (targets[i].Key == to)
					{
						return i;
					}
				}
			}
			return 0;
		}

		internal static bool Teleport(TeleportWorld portal, ZDO zdo, Player player)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			if (PrepareTargets(zdo) == 0)
			{
				((Character)player).Message((MessageType)2, PortalList.Received ? "$q8pp_none" : "$q8pp_loading", 0, (Sprite)null, false);
				return true;
			}
			Target target = targets[SelectedIndex()];
			PortalList.Entry entry = target.Entry;
			string text = sourceKey;
			if (ZoneSystem.instance.GetGlobalKey((GlobalKeys)32))
			{
				((Character)player).Message((MessageType)2, "$msg_blocked", 0, (Sprite)null, false);
				return true;
			}
			float num = default(float);
			if (ZoneSystem.instance.GetGlobalKey((GlobalKeys)33) && (RandEventSystem.instance.GetBossEvent() != null || (ZoneSystem.instance.GetGlobalKey((GlobalKeys)47, ref num) && num > 0f)))
			{
				((Character)player).Message((MessageType)2, "$msg_blockedbyboss", 0, (Sprite)null, false);
				return true;
			}
			if (!((Humanoid)player).IsTeleportable(portal.m_allowAllItems))
			{
				((Character)player).Message((MessageType)2, "$msg_noteleport", 0, (Sprite)null, false);
				return true;
			}
			Vector3 val = entry.Position + entry.Rotation * Vector3.forward * portal.m_exitDistance + Vector3.up;
			if (!((Character)player).TeleportTo(val, entry.Rotation, true))
			{
				return true;
			}
			Game.instance.IncrementPlayerStat((PlayerStatType)15, 1f, false);
			PortalPickerPlugin.Log.LogInfo((object)($"Teleporting {player.GetPlayerName()} from portal {zdo.m_uid} to {entry.Id} " + "\"" + CleanName(entry.Name) + "\""));
			TripMemory.Remember(text, target.Key);
			arrivedAt = target.Key;
			arrivedFrom = text;
			choiceFor = null;
			return true;
		}

		internal static bool Configure(TeleportWorld portal, Humanoid human)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			bool flag = PrivateArea.CheckAccess(((Component)portal).transform.position, 0f, true, false);
			if (PortalPanel.Working)
			{
				PortalPanel.Open(portal, flag);
			}
			else if (!flag)
			{
				((Character)human).Message((MessageType)2, "$piece_noaccess", 0, (Sprite)null, false);
			}
			else
			{
				TextInput.instance.RequestText((TextReceiver)(object)portal, "$piece_portal_tag", PortalPickerPlugin.NameLength.Value);
			}
			return true;
		}

		internal static string FallbackText(ZDO zdo)
		{
			string text = CleanName(zdo.GetString(ZDOVars.s_tag, ""));
			string text2 = ((text.Length > 0) ? Localization.instance.Localize("$q8pp_header").Replace("{0}", text) : Localization.instance.Localize("$q8pp_header_unnamed"));
			if (PrepareTargets(zdo) == 0)
			{
				return text2 + "\n" + Localization.instance.Localize(PortalList.Received ? "$q8pp_none" : "$q8pp_loading");
			}
			Target target = targets[SelectedIndex()];
			string text3 = ((target.Name.Length > 0) ? target.Name : Localization.instance.Localize("$q8pp_unnamed"));
			return text2 + "\n<color=yellow><b>» " + text3 + "</b></color>  " + WheelHud.FormatDistance(target.Distance) + Localization.instance.Localize("\n[<color=yellow><b>$KEY_Use</b></color>] $q8pp_go   [<color=yellow><b>$q8pp_wheel</b></color>] $q8pp_choose");
		}

		internal static string CleanName(string name)
		{
			if (!string.IsNullOrEmpty(name))
			{
				return StringExtensionMethods.RemoveRichTextTags(name).Trim();
			}
			return "";
		}

		private static void Refresh()
		{
			if (openFrame == Time.frameCount)
			{
				return;
			}
			openFrame = Time.frameCount;
			openPortal = null;
			openZdo = null;
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting() || UiOpen())
			{
				return;
			}
			GameObject hoverObject = ((Humanoid)localPlayer).GetHoverObject();
			TeleportWorld val = (((Object)(object)hoverObject != (Object)null) ? hoverObject.GetComponentInParent<TeleportWorld>() : null);
			if (!((Object)(object)val == (Object)null))
			{
				ZNetView component = ((Component)val).GetComponent<ZNetView>();
				ZDO val2 = (((Object)(object)component != (Object)null) ? component.GetZDO() : null);
				if (val2 != null)
				{
					openPortal = val;
					openZdo = val2;
				}
			}
		}

		private static bool UiOpen()
		{
			if (!InventoryGui.IsVisible() && !Menu.IsVisible() && !TextInput.IsVisible() && !Minimap.IsOpen() && !Console.IsVisible() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !StoreGui.IsVisible() && !Hud.InRadial() && !Hud.IsPieceSelectionVisible() && !GameCamera.InFreeFly() && (!((Object)(object)TextViewer.instance != (Object)null) || !TextViewer.instance.IsVisible()))
			{
				return PortalPanel.IsOpen;
			}
			return true;
		}
	}
	public static class PortalList
	{
		public struct Entry
		{
			public ZDOID Id;

			public string Name;

			public Vector3 Position;

			public Quaternion Rotation;

			public string Icon;

			public int Color;

			public long OwnerId;

			public string OwnerName;
		}

		private const string RpcPortals = "Q8PP_Portals";

		private const string RpcRequest = "Q8PP_Request";

		private const int Format = 2;

		private const float ScanInterval = 2f;

		private const float RequestInterval = 5f;

		private static List<Entry> entries = new List<Entry>();

		private static List<KeyValuePair<long, string>> players = new List<KeyValuePair<long, string>>();

		private static ulong lastHash;

		private static float nextScan;

		private static float nextRequest;

		private static ZPackage lastPackage;

		public static IReadOnlyList<Entry> Entries => entries;

		public static IReadOnlyList<KeyValuePair<long, string>> Players => players;

		public static int Version { get; private set; }

		public static bool Received { get; private set; }

		internal static void OnGameStart()
		{
			entries = new List<Entry>();
			players = new List<KeyValuePair<long, string>>();
			Version++;
			Received = false;
			lastHash = 0uL;
			nextScan = 0f;
			nextRequest = 0f;
			lastPackage = null;
			ZRoutedRpc.instance.Register<ZPackage>("Q8PP_Portals", (Action<long, ZPackage>)RPC_Portals);
			ZRoutedRpc.instance.Register("Q8PP_Request", (Action<long>)RPC_Request);
		}

		internal static void Update()
		{
			if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null || ZDOMan.instance == null || (Object)(object)Game.instance == (Object)null)
			{
				return;
			}
			if (ZNet.instance.IsServer())
			{
				if (Time.time >= nextScan)
				{
					Scan();
				}
			}
			else if (!Received && (Object)(object)Player.m_localPlayer != (Object)null && Time.time >= nextRequest)
			{
				ZNetPeer serverPeer = ZNet.instance.GetServerPeer();
				if (serverPeer != null)
				{
					nextRequest = Time.time + 5f;
					ZRoutedRpc.instance.InvokeRoutedRPC(serverPeer.m_uid, "Q8PP_Request", Array.Empty<object>());
				}
			}
		}

		public static bool HasOtherThan(ZDOID id)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			foreach (Entry entry in entries)
			{
				if (entry.Id != id)
				{
					return true;
				}
			}
			return false;
		}

		public static bool TryGet(ZDOID id, out Entry found)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			foreach (Entry entry in entries)
			{
				if (entry.Id == id)
				{
					found = entry;
					return true;
				}
			}
			found = default(Entry);
			return false;
		}

		public static void Scan()
		{
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			nextScan = Time.time + 2f;
			PlayerNames.Update();
			List<ZDO> portalList = ZDOMan.instance.GetPortalList();
			List<Entry> list = new List<Entry>(portalList.Count);
			foreach (ZDO item in portalList)
			{
				if (item != null && !((ZDOID)(ref item.m_uid)).IsNone())
				{
					long num = PortalMeta.Owner(item);
					list.Add(new Entry
					{
						Id = item.m_uid,
						Name = item.GetString(ZDOVars.s_tag, ""),
						Position = item.GetPosition(),
						Rotation = item.GetRotation(),
						Icon = PortalMeta.Icon(item),
						Color = PortalMeta.ColorCode(item),
						OwnerId = num,
						OwnerName = PlayerNames.NameOf(num)
					});
				}
			}
			list.Sort((Entry a, Entry b) => ((ZDOID)(ref a.Id)).CompareTo(b.Id));
			List<KeyValuePair<long, string>> list2 = new List<KeyValuePair<long, string>>(PlayerNames.All);
			list2.Sort((KeyValuePair<long, string> a, KeyValuePair<long, string> b) => a.Key.CompareTo(b.Key));
			ulong num2 = Hash(list, list2);
			if (!Received || num2 != lastHash)
			{
				lastHash = num2;
				entries = list;
				players = list2;
				Version++;
				Received = true;
				lastPackage = Pack(list, list2);
				int count = ZNet.instance.GetConnectedPeers().Count;
				if (count > 0)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(0L, "Q8PP_Portals", new object[1] { lastPackage });
				}
				PortalPickerPlugin.Log.LogInfo((object)$"{list.Count} portals in the world, {list2.Count} player names, list sent to {count} players");
			}
		}

		public static ZPackage Pack(List<Entry> list, List<KeyValuePair<long, string>> names)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			ZPackage val = new ZPackage();
			val.Write(2);
			val.Write(list.Count);
			foreach (Entry item in list)
			{
				val.Write(item.Id);
				val.Write(item.Name ?? "");
				val.Write(item.Position);
				val.Write(item.Rotation);
				val.Write(item.Icon ?? "");
				val.Write(item.Color);
				val.Write(item.OwnerId);
				val.Write(item.OwnerName ?? "");
			}
			val.Write(names.Count);
			foreach (KeyValuePair<long, string> name in names)
			{
				val.Write(name.Key);
				val.Write(name.Value ?? "");
			}
			return val;
		}

		public static bool Unpack(ZPackage pkg, out List<Entry> list, out List<KeyValuePair<long, string>> names)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			list = null;
			names = null;
			int num = pkg.ReadInt();
			if (num != 2)
			{
				PortalPickerPlugin.Log.LogWarning((object)$"Portal list of unknown format {num} ignored");
				return false;
			}
			int num2 = pkg.ReadInt();
			list = new List<Entry>(num2);
			for (int i = 0; i < num2; i++)
			{
				list.Add(new Entry
				{
					Id = pkg.ReadZDOID(),
					Name = pkg.ReadString(),
					Position = pkg.ReadVector3(),
					Rotation = pkg.ReadQuaternion(),
					Icon = pkg.ReadString(),
					Color = PortalMeta.NormalizeColor(pkg.ReadInt()),
					OwnerId = pkg.ReadLong(),
					OwnerName = pkg.ReadString()
				});
			}
			int num3 = pkg.ReadInt();
			names = new List<KeyValuePair<long, string>>(num3);
			for (int j = 0; j < num3; j++)
			{
				names.Add(new KeyValuePair<long, string>(pkg.ReadLong(), pkg.ReadString()));
			}
			return true;
		}

		private static void RPC_Portals(long sender, ZPackage pkg)
		{
			ZNetPeer val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerPeer() : null);
			if (val != null && !ZNet.instance.IsServer() && sender == val.m_uid && Unpack(pkg, out var list, out var names))
			{
				entries = list;
				players = names;
				Version++;
				if (!Received)
				{
					PortalPickerPlugin.Log.LogInfo((object)$"Got the list of {list.Count} portals from the server");
				}
				Received = true;
			}
		}

		private static void RPC_Request(long sender)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				if (lastPackage == null)
				{
					Scan();
				}
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, "Q8PP_Portals", new object[1] { lastPackage });
			}
		}

		private static ulong Hash(List<Entry> list, List<KeyValuePair<long, string>> names)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			ulong num = 14695981039346656037uL;
			foreach (Entry item in list)
			{
				Entry current = item;
				ulong h = num;
				ZDOID id = current.Id;
				num = Mix(h, (ulong)((ZDOID)(ref id)).UserID);
				num = Mix(num, ((ZDOID)(ref current.Id)).ID);
				num = Mix(num, current.Name);
				num = Mix(num, (ulong)Mathf.RoundToInt(current.Position.x * 10f));
				num = Mix(num, (ulong)Mathf.RoundToInt(current.Position.y * 10f));
				num = Mix(num, (ulong)Mathf.RoundToInt(current.Position.z * 10f));
				num = Mix(num, (ulong)Mathf.RoundToInt(current.Rotation.y * 1000f));
				num = Mix(num, (ulong)Mathf.RoundToInt(current.Rotation.w * 1000f));
				num = Mix(num, current.Icon);
				num = Mix(num, (ulong)current.Color);
				num = Mix(num, (ulong)current.OwnerId);
				num = Mix(num, current.OwnerName);
			}
			num = Mix(num, (ulong)list.Count);
			foreach (KeyValuePair<long, string> name in names)
			{
				num = Mix(num, (ulong)name.Key);
				num = Mix(num, name.Value);
			}
			return Mix(num, (ulong)names.Count);
		}

		private static ulong Mix(ulong h, string text)
		{
			string text2 = text ?? "";
			foreach (char c in text2)
			{
				h = Mix(h, c);
			}
			return Mix(h, 65535uL);
		}

		private static ulong Mix(ulong h, ulong value)
		{
			for (int i = 0; i < 8; i++)
			{
				h ^= (value >> i * 8) & 0xFF;
				h *= 1099511628211L;
			}
			return h;
		}
	}
	internal static class PortalMeta
	{
		private const string Rpc = "Q8PP_SetMeta";

		private static readonly int IconKey = StringExtensionMethods.GetStableHashCode("q8pp_icon");

		private static readonly int ColorKey = StringExtensionMethods.GetStableHashCode("q8pp_color");

		private static readonly int OwnerKey = StringExtensionMethods.GetStableHashCode("q8pp_owner");

		internal static readonly Color[] Palette = (Color[])(object)new Color[9]
		{
			Color32.op_Implicit(new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue)),
			Color32.op_Implicit(new Color32(byte.MaxValue, (byte)216, (byte)74, byte.MaxValue)),
			Color32.op_Implicit(new Color32(byte.MaxValue, (byte)140, (byte)40, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)230, (byte)70, (byte)58, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)240, (byte)110, (byte)180, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)160, (byte)110, (byte)240, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)80, (byte)136, (byte)247, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)60, (byte)205, (byte)200, byte.MaxValue)),
			Color32.op_Implicit(new Color32((byte)95, (byte)205, (byte)90, byte.MaxValue))
		};

		internal const int CustomFlag = 16777216;

		internal const long PublicOwner = long.MinValue;

		internal static bool IsPublic(long owner)
		{
			return owner == long.MinValue;
		}

		internal static string Icon(ZDO zdo)
		{
			return zdo.GetString(IconKey, "");
		}

		internal static int ColorCode(ZDO zdo)
		{
			return NormalizeColor(zdo.GetInt(ColorKey, 0));
		}

		internal static long Owner(ZDO zdo)
		{
			long num = zdo.GetLong(OwnerKey, 0L);
			if (num == 0L)
			{
				return zdo.GetLong(ZDOVars.s_creator, 0L);
			}
			return num;
		}

		internal static bool IsCustom(int code)
		{
			return (code & -16777216) == 16777216;
		}

		internal static int NormalizeColor(int code)
		{
			if (!IsCustom(code) && (code < 0 || code >= Palette.Length))
			{
				return 0;
			}
			return code;
		}

		internal static Color ColorOf(int code)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (IsCustom(code))
			{
				return Color32.op_Implicit(new Color32((byte)(code >> 16), (byte)(code >> 8), (byte)code, byte.MaxValue));
			}
			return Palette[NormalizeColor(code)];
		}

		internal static int CodeOf(Color32 c)
		{
			//IL_000a: 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_0015: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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)
			for (int i = 0; i < Palette.Length; i++)
			{
				Color32 val = Color32.op_Implicit(Palette[i]);
				if (val.r == c.r && val.g == c.g && val.b == c.b)
				{
					return i;
				}
			}
			return 0x1000000 | (c.r << 16) | (c.g << 8) | c.b;
		}

		internal static void Register(ZNetView view)
		{
			view.Register<ZPackage>("Q8PP_SetMeta", (Action<long, ZPackage>)delegate(long sender, ZPackage pkg)
			{
				Apply(view, pkg);
			});
		}

		internal static void Send(ZNetView view, string name, string icon, int color, long owner)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)view == (Object)null) && view.IsValid())
			{
				ZPackage val = new ZPackage();
				val.Write(name ?? "");
				val.Write(((object)((IUser)PlatformManager.DistributionPlatform.LocalUser).PlatformUserID/*cast due to .constrained prefix*/).ToString());
				val.Write(icon ?? "");
				val.Write(NormalizeColor(color));
				val.Write(owner);
				view.InvokeRPC("Q8PP_SetMeta", new object[1] { val });
			}
		}

		private static void Apply(ZNetView view, ZPackage pkg)
		{
			if (!((Object)(object)view == (Object)null) && view.IsValid() && view.IsOwner())
			{
				string text = pkg.ReadString();
				string text2 = pkg.ReadString();
				string text3 = pkg.ReadString();
				int num = NormalizeColor(pkg.ReadInt());
				long num2 = pkg.ReadLong();
				ZDO zDO = view.GetZDO();
				zDO.Set(ZDOVars.s_tag, text);
				zDO.Set(ZDOVars.s_tagauthor, text2);
				zDO.Set(IconKey, text3);
				zDO.Set(ColorKey, num, false);
				if (num2 != 0L)
				{
					zDO.Set(OwnerKey, num2);
				}
			}
		}
	}
	internal static class PortalPanel
	{
		private sealed class IconCell
		{
			public RectTransform Rect;

			public Image Edge;

			public Image Icon;

			public TextMeshProUGUI Mark;

			public IconDef Def;

			public string Key;

			public bool Hover;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Comparison<KeyValuePair<long, string>> <>9__82_0;

			public static Converter<int, string> <>9__110_0;

			public static UnityAction<string> <>9__115_0;

			public static UnityAction<int> <>9__115_1;

			public static UnityAction <>9__115_2;

			public static UnityAction <>9__115_3;

			public static UnityAction <>9__115_4;

			public static UnityAction<int> <>9__117_0;

			public static UnityAction<string> <>9__119_0;

			internal int <FillOwners>b__82_0(KeyValuePair<long, string> a, KeyValuePair<long, string> b)
			{
				return string.Compare(a.Value, b.Value, StringComparison.CurrentCultureIgnoreCase);
			}

			internal string <RememberRecentColor>b__110_0(int c)
			{
				return (c & 0xFFFFFF).ToString("X6", CultureInfo.InvariantCulture);
			}

			internal void <BuildMain>b__115_0(string _)
			{
				RefreshPreview();
			}

			internal void <BuildMain>b__115_1(int i)
			{
				if (i >= 0 && i < ownerIds.Count)
				{
					pickedOwner = ownerIds[i];
					RefreshPreview();
				}
			}

			internal void <BuildMain>b__115_2()
			{
				if (!readOnly)
				{
					ShowPalette(show: true);
				}
			}

			internal void <BuildMain>b__115_3()
			{
				Close(save: false);
			}

			internal void <BuildMain>b__115_4()
			{
				Close(save: true);
			}

			internal void <BuildFavoriteDropdown>b__117_0(int i)
			{
				if (i >= 0 && i < favoriteKeys.Count)
				{
					pickedFavorite = favoriteKeys[i];
					RefreshFavoriteCaption();
				}
			}

			internal void <BuildAll>b__119_0(string _)
			{
				Filter();
			}
		}

		private const int RecentShown = 8;

		private const int RecentKept = 16;

		private const int Cols = 10;

		private const int VisibleRows = 6;

		private const float Cell = 46f;

		private const float Gap = 7f;

		private const float Pitch = 53f;

		private const int ConvertPerFrame = 8;

		private const float MaxDistance = 8f;

		private const float PaletteX = 538f;

		private const int RecentColorsShown = 10;

		private const float SquareSize = 250f;

		private const float StripWidth = 24f;

		private static GameObject root;

		private static GameObject mainPanel;

		private static GameObject allPanel;

		private static GameObject palettePanel;

		private static bool blocking;

		private static bool faulted;

		private static InputField nameField;

		private static Dropdown ownerDropdown;

		private static readonly List<long> ownerIds = new List<long>();

		private static readonly IconCell[] row = new IconCell[10];

		private static readonly Image[] swatches = (Image[])(object)new Image[9];

		private static Image paletteButton;

		private static Image paletteBadge;

		private static Image swatchRing;

		private static Image previewIcon;

		private static TextMeshProUGUI previewText;

		private static Dropdown favoriteDropdown;

		private static Image favoriteStar;

		private static readonly List<string> favoriteKeys = new List<string>();

		private static readonly List<Color> favoriteColors = new List<Color>();

		private static TextMeshProUGUI mainHint;

		private static InputField search;

		private static IconCategory tab = IconCategory.All;

		private static readonly TextMeshProUGUI[] tabLabels = (TextMeshProUGUI[])(object)new TextMeshProUGUI[7];

		private static readonly Image[] tabMarks = (Image[])(object)new Image[7];

		private static ScrollRect scroll;

		private static RectTransform viewport;

		private static RectTransform content;

		private static readonly IconCell[] pool = new IconCell[70];

		private static readonly List<IconDef> filtered = new List<IconDef>();

		private static RectTransform tooltip;

		private static TextMeshProUGUI tooltipText;

		private static int firstRow = -1;

		private static ColorField square;

		private static ColorField strip;

		private static RectTransform squareMark;

		private static RectTransform stripMark;

		private static InputField hexField;

		private static Image paletteSample;

		private static Image palettePreviewIcon;

		private static TextMeshProUGUI palettePreviewText;

		private static readonly Image[] recentSwatches = (Image[])(object)new Image[10];

		private static readonly List<int> recentCodes = new List<int>();

		private static TextMeshProUGUI recentCaption;

		private static float hue;

		private static float sat;

		private static float val;

		private static Color32 paletteColor;

		private static TeleportWorld portal;

		private static ZNetView view;

		private static string pickedIcon = "";

		private static int pickedColor;

		private static long pickedOwner;

		private static long startOwner;

		private static bool readOnly;

		private static string portalKey;

		private static string pickedFavorite;

		private static string shownFavorite;

		internal static bool IsOpen
		{
			get
			{
				if ((Object)(object)root != (Object)null)
				{
					return root.activeSelf;
				}
				return false;
			}
		}

		internal static bool Working => !faulted;

		internal static void Reset()
		{
			if (blocking)
			{
				GUIManager.BlockInput(false);
			}
			blocking = false;
			faulted = false;
			if ((Object)(object)root != (Object)null)
			{
				Object.Destroy((Object)(object)root);
			}
			root = null;
			portal = null;
			view = null;
		}

		internal static void Open(TeleportWorld target, bool canEdit)
		{
			if (faulted)
			{
				return;
			}
			try
			{
				OpenCore(target, canEdit);
			}
			catch (Exception ex)
			{
				faulted = true;
				Close(save: false);
				PortalPickerPlugin.Log.LogError((object)("Portal window is switched off until you re-enter the world: " + ex));
			}
		}

		internal static void Update()
		{
			if (!IsOpen)
			{
				return;
			}
			try
			{
				UpdateCore();
			}
			catch (Exception ex)
			{
				faulted = true;
				Close(save: false);
				PortalPickerPlugin.Log.LogError((object)("Portal window is switched off until you re-enter the world: " + ex));
			}
		}

		private static void OpenCore(TeleportWorld target, bool canEdit)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			view = ((Component)target).GetComponent<ZNetView>();
			ZDO val = (((Object)(object)view != (Object)null) ? view.GetZDO() : null);
			if (val != null)
			{
				if ((Object)(object)root == (Object)null)
				{
					Build();
				}
				portal = target;
				readOnly = !canEdit;
				portalKey = TripMemory.KeyOf(val.GetPosition());
				pickedIcon = PortalMeta.Icon(val);
				pickedColor = PortalMeta.ColorCode(val);
				startOwner = (pickedOwner = PortalMeta.Owner(val));
				nameField.characterLimit = PortalPickerPlugin.NameLength.Value;
				nameField.text = val.GetString(ZDOVars.s_tag, "");
				((Selectable)nameField).interactable = !readOnly;
				FillOwners();
				if (readOnly)
				{
					((Selectable)ownerDropdown).interactable = false;
				}
				RefreshRow();
				RefreshSwatches();
				FillFavorites(val);
				((TMP_Text)mainHint).text = Localization.instance.Localize(readOnly ? "$q8pp_ward_favorite_only" : "<b>Enter</b> — $q8pp_keys_save   <b>Esc</b> — $q8pp_keys_cancel");
				allPanel.SetActive(false);
				palettePanel.SetActive(false);
				mainPanel.SetActive(true);
				root.SetActive(true);
				if (!blocking)
				{
					GUIManager.BlockInput(true);
					blocking = true;
				}
				if (!readOnly)
				{
					((Selectable)nameField).Select();
					nameField.ActivateInputField();
				}
			}
		}

		private static void Close(bool save)
		{
			if (save && (Object)(object)view != (Object)null && view.IsValid())
			{
				if (!readOnly)
				{
					string text = (nameField.text ?? "").Trim();
					if (text.Length > PortalPickerPlugin.NameLength.Value)
					{
						text = text.Substring(0, PortalPickerPlugin.NameLength.Value);
					}
					PortalMeta.Send(view, text, pickedIcon, pickedColor, (pickedOwner != startOwner) ? pickedOwner : 0);
					RememberRecent(pickedIcon);
					RememberRecentColor(pickedColor);
				}
				if (pickedFavorite != shownFavorite)
				{
					TripMemory.SetFavorite(portalKey, pickedFavorite);
				}
			}
			if ((Object)(object)root != (Object)null)
			{
				root.SetActive(false);
			}
			if (blocking)
			{
				GUIManager.BlockInput(false);
				blocking = false;
			}
			portal = null;
			view = null;
		}

		private static void UpdateCore()
		{
			//IL_004b: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)portal == (Object)null || (Object)(object)view == (Object)null || !view.IsValid() || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting() || Vector3.Distance(((Component)localPlayer).transform.position, ((Component)portal).transform.position) > 8f)
			{
				Close(save: false);
				return;
			}
			if (allPanel.activeSelf)
			{
				if (ZInput.GetKeyDown((KeyCode)27, true))
				{
					ShowAll(show: false);
					return;
				}
				float mouseScrollWheel = ZInput.GetMouseScrollWheel();
				if (mouseScrollWheel != 0f && RectTransformUtility.RectangleContainsScreenPoint(viewport, Vector2.op_Implicit(ZInput.pointerPosition), EventCamera()))
				{
					Rect rect = content.rect;
					float height = ((Rect)(ref rect)).height;
					rect = viewport.rect;
					float num = Mathf.Max(0f, height - ((Rect)(ref rect)).height);
					Vector2 anchoredPosition = content.anchoredPosition;
					anchoredPosition.y = Mathf.Clamp(anchoredPosition.y + ((mouseScrollWheel < 0f) ? 53f : (-53f)), 0f, num);
					content.anchoredPosition = anchoredPosition;
				}
				LayoutPool(force: false);
				ConvertVisible();
				return;
			}
			if (palettePanel.activeSelf)
			{
				if (ZInput.GetKeyDown((KeyCode)27, true))
				{
					ShowPalette(show: false);
				}
				else if (ZInput.GetKeyDown((KeyCode)13, true) || ZInput.GetKeyDown((KeyCode)271, true))
				{
					PickColor(PortalMeta.CodeOf(paletteColor));
				}
				return;
			}
			TintFavoriteIcons();
			if (ZInput.GetKeyDown((KeyCode)27, true))
			{
				if (!HideOpenList(ownerDropdown) && !HideOpenList(favoriteDropdown))
				{
					Close(save: false);
				}
			}
			else if (ZInput.GetKeyDown((KeyCode)13, true) || ZInput.GetKeyDown((KeyCode)271, true))
			{
				Close(save: true);
			}
		}

		private static void FillOwners()
		{
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Expected O, but got Unknown
			long num = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0);
			Dictionary<long, string> dictionary = new Dictionary<long, string>();
			foreach (KeyValuePair<long, string> player in PortalList.Players)
			{
				dictionary[player.Key] = player.Value;
			}
			if (num != 0L && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				dictionary[num] = Player.m_localPlayer.GetPlayerName();
			}
			if (!PortalMeta.IsPublic(startOwner) && !dictionary.ContainsKey(startOwner))
			{
				dictionary[startOwner] = Localization.instance.Localize("$q8pp_unknown_owner");
			}
			List<KeyValuePair<long, string>> list = new List<KeyValuePair<long, string>>(dictionary);
			list.Sort((KeyValuePair<long, string> a, KeyValuePair<long, string> b) => string.Compare(a.Value, b.Value, StringComparison.CurrentCultureIgnoreCase));
			ownerIds.Clear();
			ownerIds.Add(long.MinValue);
			List<OptionData> list2 = new List<OptionData>
			{
				new OptionData(Localization.instance.Localize("$q8pp_owner_public"))
			};
			int valueWithoutNotify = 0;
			foreach (KeyValuePair<long, string> item in list)
			{
				if (item.Key == startOwner)
				{
					valueWithoutNotify = ownerIds.Count;
				}
				ownerIds.Add(item.Key);
				list2.Add(new OptionData(item.Value));
			}
			ownerDropdown.ClearOptions();
			ownerDropdown.AddOptions(list2);
			ownerDropdown.SetValueWithoutNotify(valueWithoutNotify);
			ownerDropdown.RefreshShownValue();
			((Selectable)ownerDropdown).interactable = true;
		}

		private static List<string> Recent()
		{
			List<string> list = new List<string>();
			string[] array = (PortalPickerPlugin.RecentIcons.Value ?? "").Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0 && !list.Contains(text) && IconLibrary.Find(text) != null)
				{
					list.Add(text);
				}
			}
			array = IconLibrary.DefaultRecent;
			foreach (string text2 in array)
			{
				if (list.Count >= 8)
				{
					break;
				}
				if (!list.Contains(text2) && IconLibrary.Find(text2) != null)
				{
					list.Add(text2);
				}
			}
			return list;
		}

		private static void RememberRecent(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return;
			}
			List<string> list = new List<string> { key };
			foreach (string item in Recent())
			{
				if (item != key && list.Count < 16)
				{
					list.Add(item);
				}
			}
			PortalPickerPlugin.RecentIcons.Value = string.Join(",", list);
		}

		private static void RefreshRow()
		{
			List<string> list = Recent();
			List<string> list2 = new List<string>();
			if (!string.IsNullOrEmpty(pickedIcon) && IconLibrary.Find(pickedIcon) != null)
			{
				list2.Add(pickedIcon);
			}
			foreach (string item in list)
			{
				if (list2.Count >= 8)
				{
					break;
				}
				if (item != pickedIcon)
				{
					list2.Add(item);
				}
			}
			for (int i = 0; i < 8; i++)
			{
				IconCell iconCell = row[i + 1];