Decompiled source of PortalSelector v1.0.1

Landoria.PortalSelector.dll

Decompiled 17 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using GUIFramework;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Landoria.PortalSelector")]
[assembly: AssemblyDescription("Adds shared portal names and destinations to Valheim.")]
[assembly: AssemblyCompany("Landoria")]
[assembly: AssemblyProduct("Landoria.PortalSelector")]
[assembly: AssemblyCopyright("Copyright © 2026 Landoria")]
[assembly: ComVisible(false)]
[assembly: Guid("E2FE30E1-DCF1-4BD7-9776-035DC9FAA2DF")]
[assembly: AssemblyFileVersion("1.0.1")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.1.13809")]
[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 Landoria.PortalSelector
{
	internal static class PlayerPortalCatalog
	{
		private const int Format = 1;

		internal static void Load(Player player, string key, Dictionary<Guid, PortalRecord> records)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			if (!player.m_customData.TryGetValue(key, out var value) || string.IsNullOrEmpty(value))
			{
				Plugin.DebugLog("Catalog: no saved data for this world.");
				return;
			}
			try
			{
				ZPackage val = new ZPackage(Convert.FromBase64String(value));
				if (val.ReadInt() != 1)
				{
					Plugin.WarningLog("Catalog: unsupported format; ignoring saved data.");
					return;
				}
				int num = Mathf.Clamp(val.ReadInt(), 0, 10000);
				for (int i = 0; i < num; i++)
				{
					PortalRecord portalRecord = ReadRecord(val);
					if (portalRecord.Guid != Guid.Empty)
					{
						records[portalRecord.Guid] = portalRecord;
					}
				}
				Plugin.DebugLog("Catalog: loaded " + records.Count + " portals.");
			}
			catch (Exception ex)
			{
				records.Clear();
				Plugin.WarningLog("Catalog: load failed (" + ex.GetType().Name + ").");
			}
		}

		internal static void Save(Player player, string key, Dictionary<Guid, PortalRecord> records)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			try
			{
				ZPackage val = new ZPackage();
				val.Write(1);
				val.Write(records.Count);
				foreach (PortalRecord value in records.Values)
				{
					WriteRecord(val, value);
				}
				player.m_customData[key] = Convert.ToBase64String(val.GetArray());
			}
			catch (Exception ex)
			{
				Plugin.WarningLog("Catalog: save failed (" + ex.GetType().Name + ").");
			}
		}

		private static PortalRecord ReadRecord(ZPackage package)
		{
			//IL_0024: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			return new PortalRecord
			{
				Guid = Guid.Parse(package.ReadString()),
				LastKnownName = package.ReadString(),
				Position = package.ReadVector3(),
				Biome = (Biome)package.ReadInt()
			};
		}

		private static void WriteRecord(ZPackage package, PortalRecord record)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected I4, but got Unknown
			package.Write(record.Guid.ToString("D"));
			package.Write(record.LastKnownName ?? "");
			package.Write(record.Position);
			package.Write((int)record.Biome);
		}
	}
	internal static class PortalDirectory
	{
		private sealed class StartupEntry
		{
			internal readonly Guid Guid;

			internal readonly Vector3 Position;

			internal readonly bool Known;

			internal float FirstSync = -1f;

			internal int Syncs;

			internal StartupEntry(Guid guid, Vector3 position, bool known)
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				Guid = guid;
				Position = position;
				Known = known;
			}
		}

		private const string CatalogPrefix = "Landoria.PortalSelector.CatalogGuidV1.";

		private static readonly Dictionary<Guid, PortalRecord> Records = new Dictionary<Guid, PortalRecord>();

		private static readonly Dictionary<ZDOID, Guid> SeenIds = new Dictionary<ZDOID, Guid>();

		private static readonly HashSet<Guid> RemovedIds = new HashSet<Guid>();

		private static Player _player;

		private static string _catalogKey;

		private static float _nextScan;

		private const float StartupTimeout = 5f;

		private const float StartupSpacing = 0.25f;

		private const int MaxStartupCandidates = 2048;

		private static readonly Queue<StartupEntry> StartupQueue = new Queue<StartupEntry>();

		private static readonly HashSet<Guid> StartupScheduled = new HashSet<Guid>();

		private static ZNet _startupSession;

		private static StartupEntry _startupCurrent;

		private static bool _startupRequested;

		private static bool _startupStarted;

		private static bool _startupCompleted;

		private static float _nextStartupCheck;

		private static int _startupChecked;

		private static int _startupRemoved;

		internal static void Update()
		{
			if (!((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)ZNet.instance == (Object)null) && ZDOMan.instance != null)
			{
				LoadSession();
				if (Time.unscaledTime >= _nextScan)
				{
					Scan();
				}
				UpdateStartupCleanup();
			}
		}

		internal static void ScanNow()
		{
			_nextScan = 0f;
			Update();
		}

		private static void Scan()
		{
			_nextScan = Time.unscaledTime + 5f;
			List<ZDO> portals = new List<ZDO>(ZDOMan.instance.GetPortalList());
			if ((0u | (ScanObjects(portals) ? 1u : 0u) | (RefreshBiomes() ? 1u : 0u)) != 0)
			{
				PlayerPortalCatalog.Save(_player, _catalogKey, Records);
			}
		}

		private static bool ScanObjects(List<ZDO> portals)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			HashSet<ZDOID> hashSet = new HashSet<ZDOID>();
			for (int i = 0; i < portals.Count; i++)
			{
				ZDO val = portals[i];
				if (!hashSet.Add(val.m_uid))
				{
					continue;
				}
				flag |= ScanPortal(val);
				ZDOID connectionZDOID = val.GetConnectionZDOID((ConnectionType)1);
				if (!(connectionZDOID == ZDOID.None))
				{
					ZDO target = PortalConnection.GetTarget(connectionZDOID);
					if (target != null)
					{
						portals.Add(target);
					}
				}
			}
			return flag;
		}

		private static bool ScanPortal(ZDO portal)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			PortalFields.EnsureIdentity(portal.m_uid);
			PortalRecord portalRecord = CreateRecord(portal);
			if (portalRecord == null)
			{
				return false;
			}
			int num;
			if (!Records.ContainsKey(portalRecord.Guid))
			{
				num = ((!RemovedIds.Contains(portalRecord.Guid)) ? 1 : 0);
				if (num != 0)
				{
					PortalVanillaImport.TryImport(portal, portalRecord);
				}
			}
			else
			{
				num = 0;
			}
			bool result = UpdateRecord(portal);
			if (num != 0 && Records.TryGetValue(portalRecord.Guid, out var value))
			{
				PortalPeerSync.AnnouncePortal(portal.m_uid, value);
			}
			return result;
		}

		private static bool RefreshBiomes()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (WorldGenerator.instance == null)
			{
				return false;
			}
			bool result = false;
			foreach (PortalRecord value in Records.Values)
			{
				Biome val = ResolveBiome(value.Position);
				if (value.Biome != val)
				{
					value.Biome = val;
					result = true;
				}
			}
			return result;
		}

		internal static float NearestOtherPortalDistanceSquared(PortalRecord record, PortalRecord partner)
		{
			float num = float.PositiveInfinity;
			foreach (PortalRecord value in Records.Values)
			{
				if (!(value.Guid == record.Guid) && (partner == null || !(value.Guid == partner.Guid)))
				{
					float num2 = record.Position.x - value.Position.x;
					float num3 = record.Position.z - value.Position.z;
					num = Math.Min(num, num2 * num2 + num3 * num3);
				}
			}
			return num;
		}

		internal static PortalRecord Find(Guid guid)
		{
			LoadSession();
			Records.TryGetValue(guid, out var value);
			return value;
		}

		internal static PortalRecord Find(ZDOID id)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			LoadSession();
			PortalZdoData portalZdoData = PortalFields.Read(id);
			if (portalZdoData != null && portalZdoData.Guid != Guid.Empty)
			{
				return Find(portalZdoData.Guid);
			}
			if (!SeenIds.TryGetValue(id, out var value))
			{
				return null;
			}
			return Find(value);
		}

		internal static bool Remember(ZDO portal)
		{
			//IL_0018: 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)
			LoadSession();
			if ((Object)(object)_player == (Object)null || portal == null)
			{
				return false;
			}
			PortalFields.EnsureIdentity(portal.m_uid);
			PortalRecord portalRecord = CreateRecord(portal);
			if (portalRecord == null)
			{
				return false;
			}
			int num;
			if (!Records.ContainsKey(portalRecord.Guid))
			{
				num = ((!RemovedIds.Contains(portalRecord.Guid)) ? 1 : 0);
				if (num != 0)
				{
					PortalVanillaImport.TryImport(portal, portalRecord);
				}
			}
			else
			{
				num = 0;
			}
			if (UpdateRecord(portal))
			{
				PlayerPortalCatalog.Save(_player, _catalogKey, Records);
			}
			if (num != 0 && Records.TryGetValue(portalRecord.Guid, out var value))
			{
				PortalPeerSync.AnnouncePortal(portal.m_uid, value);
			}
			return true;
		}

		internal static List<PortalRecord> KnownRecords()
		{
			LoadSession();
			return new List<PortalRecord>(Records.Values);
		}

		internal static void CacheName(ZDOID id, string name)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			LoadSession();
			if ((Object)(object)_player == (Object)null || string.IsNullOrWhiteSpace(name))
			{
				return;
			}
			PortalRecord portalRecord = Find(id);
			if (portalRecord != null && !(portalRecord.LastKnownName == name))
			{
				portalRecord.LastKnownName = name;
				PlayerPortalCatalog.Save(_player, _catalogKey, Records);
				ZDO target = PortalConnection.GetTarget(id);
				if (target != null && target.IsOwner())
				{
					PortalPeerSync.AnnouncePortal(id, portalRecord);
				}
			}
		}

		private static void LoadSession()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)ZNet.instance == (Object)null) && !((Object)(object)localPlayer == (Object)null))
			{
				string text = "Landoria.PortalSelector.CatalogGuidV1." + ZNet.instance.GetWorldUID();
				if (_player != localPlayer || !(_catalogKey == text))
				{
					_player = localPlayer;
					_catalogKey = text;
					_nextScan = 0f;
					Records.Clear();
					SeenIds.Clear();
					RemovedIds.Clear();
					PlayerDestinations.Reset();
					PortalConnection.Reset();
					PlayerPortalCatalog.Load(localPlayer, text, Records);
					Plugin.DebugLog("Catalog: world session ready, records=" + Records.Count + ".");
				}
			}
		}

		private static bool UpdateRecord(ZDO portal)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			PortalRecord portalRecord = CreateRecord(portal);
			if (portalRecord == null)
			{
				return false;
			}
			if (RemovedIds.Contains(portalRecord.Guid))
			{
				return false;
			}
			SeenIds[portal.m_uid] = portalRecord.Guid;
			return StoreRecord(portalRecord);
		}

		internal static PortalRecord CreateRecord(ZDO portal)
		{
			//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_004e: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if (portal == null)
			{
				return null;
			}
			if (WorldGenerator.instance == null)
			{
				return null;
			}
			PortalZdoData portalZdoData = PortalFields.Read(portal);
			if (portalZdoData.Guid == Guid.Empty)
			{
				return null;
			}
			Vector3 position = portalZdoData.Position;
			return new PortalRecord
			{
				Guid = portalZdoData.Guid,
				LastKnownName = portalZdoData.Name,
				Position = position,
				Biome = ResolveBiome(position)
			};
		}

		private static bool StoreRecord(PortalRecord record)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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)
			PortalRecord value;
			bool num = Records.TryGetValue(record.Guid, out value);
			if (num && string.IsNullOrWhiteSpace(record.LastKnownName))
			{
				record.LastKnownName = value.LastKnownName;
			}
			bool result = !num || value.LastKnownName != record.LastKnownName || value.Position != record.Position || value.Biome != record.Biome;
			Records[record.Guid] = record;
			if (!num)
			{
				Guid guid = record.Guid;
				Plugin.DebugLog("Catalog: discovered guid=" + guid.ToString() + ".");
			}
			return result;
		}

		private static Biome ResolveBiome(Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Biome val = Heightmap.FindBiome(position);
			if ((int)val == 0)
			{
				return WorldGenerator.instance.GetBiomeSector(position, false).Biome;
			}
			return val;
		}

		internal unsafe static void OnDestroyedZDO(ZDOMan manager, ZDOID id)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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)
			Player localPlayer = Player.m_localPlayer;
			ZNet instance = ZNet.instance;
			if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)instance == (Object)null) && manager == ZDOMan.instance)
			{
				LoadSession();
				Guid guid = Find(id)?.Guid ?? PortalFields.Read(id)?.Guid ?? Guid.Empty;
				if (guid == Guid.Empty && SeenIds.TryGetValue(id, out var value))
				{
					guid = value;
				}
				SeenIds.Remove(id);
				if (!(guid == Guid.Empty) && RemovePortal(guid))
				{
					PortalPeerSync.AnnounceRemoval(guid);
					ZDOID val = id;
					Plugin.DebugLog("Catalog: destroyed portal removed zdo=" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString() + ".");
				}
			}
		}

		internal static void OnPeerRemoval(Guid guid)
		{
			LoadSession();
			if ((Object)(object)_player != (Object)null && RemovePortal(guid))
			{
				Guid guid2 = guid;
				Plugin.DebugLog("Catalog: peer removed guid=" + guid2.ToString() + ".");
			}
		}

		private static bool RemovePortal(Guid guid)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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)
			if (guid == Guid.Empty || !RemovedIds.Add(guid))
			{
				return false;
			}
			PlayerDestinations.ForgetPortal(guid);
			List<ZDOID> list = new List<ZDOID>();
			foreach (KeyValuePair<ZDOID, Guid> seenId in SeenIds)
			{
				if (seenId.Value == guid)
				{
					list.Add(seenId.Key);
				}
			}
			foreach (ZDOID item in list)
			{
				SeenIds.Remove(item);
			}
			if (Records.Remove(guid))
			{
				PlayerPortalCatalog.Save(_player, _catalogKey, Records);
			}
			PortalDialog.OnPortalRemoved(guid);
			return true;
		}

		internal static void OnPeerPortal(ZDOID id, Guid guid, string name, Vector3 position)
		{
			//IL_0027: 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_0054: 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_005b: 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)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			LoadSession();
			if (!((Object)(object)_player == (Object)null) && WorldGenerator.instance != null && !RemovedIds.Contains(guid))
			{
				if (id != ZDOID.None)
				{
					SeenIds[id] = guid;
				}
				if (StoreRecord(new PortalRecord
				{
					Guid = guid,
					LastKnownName = name,
					Position = position,
					Biome = ResolveBiome(position)
				}))
				{
					PlayerPortalCatalog.Save(_player, _catalogKey, Records);
					PortalDialog.OnPortalUpdated(Records[guid]);
					Guid guid2 = guid;
					Plugin.DebugLog("Catalog: peer portal guid=" + guid2.ToString() + ".");
				}
			}
		}

		internal static void Request(ZDOID origin)
		{
			//IL_0005: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			ScanNow();
			if (Find(origin) == null || !PlayerPortalNames.IsNamed(origin))
			{
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, "Name this portal before choosing a destination.", 0, (Sprite)null, false);
				}
			}
			else
			{
				PortalDialog.Open(origin, Records.Values.Where((PortalRecord record) => !string.IsNullOrWhiteSpace(record.LastKnownName)).ToList());
			}
		}

		internal static void BeginStartupCleanup()
		{
			if ((Object)(object)_startupSession != (Object)(object)ZNet.instance)
			{
				ResetStartupCleanup();
				_startupSession = ZNet.instance;
			}
			if (!_startupStarted && !_startupCompleted)
			{
				_startupRequested = true;
				Plugin.DebugLog("Startup: first spawn requested catalog check.");
			}
		}

		internal static void ResetStartupCleanup()
		{
			StartupQueue.Clear();
			StartupScheduled.Clear();
			_startupSession = null;
			_startupCurrent = null;
			_startupRequested = false;
			_startupStarted = false;
			_startupCompleted = false;
			_startupChecked = 0;
			_startupRemoved = 0;
		}

		private static void UpdateStartupCleanup()
		{
			if (!_startupRequested && !_startupStarted)
			{
				return;
			}
			if ((Object)(object)_startupSession != (Object)(object)ZNet.instance || (Object)(object)_player != (Object)(object)Player.m_localPlayer)
			{
				ResetStartupCleanup();
				return;
			}
			if (_startupRequested && WorldGenerator.instance != null)
			{
				StartStartupCleanup();
			}
			if (_startupStarted)
			{
				if (_startupCurrent != null)
				{
					CheckStartupCurrent();
				}
				else if (Time.unscaledTime >= _nextStartupCheck)
				{
					DispatchStartupCheck();
				}
				if (_startupCurrent == null && StartupQueue.Count == 0)
				{
					FinishStartupCleanup();
				}
			}
		}

		private static void StartStartupCleanup()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			_startupRequested = false;
			_startupStarted = true;
			_nextStartupCheck = Time.unscaledTime;
			foreach (PortalRecord value in Records.Values)
			{
				ScheduleStartupCheck(value.Guid, value.Position, known: true);
			}
			Plugin.DebugLog("Startup: checking " + StartupQueue.Count + " saved portals.");
			PortalPeerSync.RequestSnapshot();
		}

		private static void DispatchStartupCheck()
		{
			//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)
			if (StartupQueue.Count == 0)
			{
				return;
			}
			_startupCurrent = StartupQueue.Dequeue();
			string[] obj = new string[7]
			{
				"Startup: checking guid=",
				_startupCurrent.Guid.ToString(),
				" known=",
				null,
				null,
				null,
				null
			};
			bool known = _startupCurrent.Known;
			obj[3] = known.ToString();
			obj[4] = " near=";
			obj[5] = ((object)_startupCurrent.Position/*cast due to .constrained prefix*/).ToString();
			obj[6] = ".";
			Plugin.DebugLog(string.Concat(obj));
			if (_startupCurrent.Known && !Records.ContainsKey(_startupCurrent.Guid))
			{
				Plugin.DebugLog("Startup: skipped removed guid=" + _startupCurrent.Guid.ToString() + ".");
				ReleaseStartupCheck();
				return;
			}
			ZDO val = PortalConnection.FindLoaded(_startupCurrent.Guid);
			if (val != null)
			{
				ConfirmStartupPortal(val);
				ReleaseStartupCheck();
			}
			else if (ZNet.instance.IsServer())
			{
				Plugin.DebugLog("Startup: host has no matching portal guid=" + _startupCurrent.Guid.ToString() + ".");
				ExpireStartupCheck();
				ReleaseStartupCheck();
			}
		}

		private static void CheckStartupCurrent()
		{
			if (_startupCurrent.Known && !Records.ContainsKey(_startupCurrent.Guid))
			{
				ReleaseStartupCheck();
				return;
			}
			ZDO val = PortalConnection.FindLoaded(_startupCurrent.Guid);
			Vector3 position;
			if (val != null)
			{
				ConfirmStartupPortal(val);
				ReleaseStartupCheck();
			}
			else if (PortalConnection.TryGetInterest(out position))
			{
				if (_startupCurrent.FirstSync >= 0f)
				{
					Plugin.DebugLog("Startup: travel paused check guid=" + _startupCurrent.Guid.ToString() + ".");
				}
				_startupCurrent.FirstSync = -1f;
				_startupCurrent.Syncs = 0;
			}
			else if (_startupCurrent.FirstSync >= 0f && _startupCurrent.Syncs >= 2 && Time.unscaledTime - _startupCurrent.FirstSync >= 5f)
			{
				ExpireStartupCheck();
				ReleaseStartupCheck();
			}
		}

		internal static bool TryGetStartupInterest(out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			position = Vector3.zero;
			if (_startupCurrent == null || (Object)(object)_startupSession != (Object)(object)ZNet.instance || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer())
			{
				return false;
			}
			position = (Records.TryGetValue(_startupCurrent.Guid, out var value) ? value.Position : _startupCurrent.Position);
			return true;
		}

		internal static void MarkStartupInterestSent()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if (_startupCurrent != null)
			{
				if (_startupCurrent.FirstSync < 0f)
				{
					_startupCurrent.FirstSync = Time.unscaledTime;
					Plugin.DebugLog("Startup: requesting guid=" + _startupCurrent.Guid.ToString() + " near=" + ((object)_startupCurrent.Position/*cast due to .constrained prefix*/).ToString() + ".");
				}
				_startupCurrent.Syncs++;
				Plugin.DebugLog("Startup: area sync guid=" + _startupCurrent.Guid.ToString() + " count=" + _startupCurrent.Syncs + ".");
			}
		}

		private unsafe static void ConfirmStartupPortal(ZDO portal)
		{
			//IL_006c: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: 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)
			PortalZdoData portalZdoData = PortalFields.Read(portal);
			PortalRecord value;
			string text = (Records.TryGetValue(portalZdoData.Guid, out value) ? value.LastKnownName : null);
			if (!Remember(portal))
			{
				return;
			}
			PortalRecord portalRecord = Find(portalZdoData.Guid);
			string[] obj = new string[9] { "Startup: live portal guid=", null, null, null, null, null, null, null, null };
			Guid guid = portalZdoData.Guid;
			obj[1] = guid.ToString();
			obj[2] = " zdo=";
			ZDOID uid = portal.m_uid;
			obj[3] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
			obj[4] = " name='";
			obj[5] = portalRecord?.LastKnownName;
			obj[6] = "' position=";
			obj[7] = (portalRecord?.Position).ToString();
			obj[8] = ".";
			Plugin.DebugLog(string.Concat(obj));
			if (portalRecord != null && text != portalRecord.LastKnownName)
			{
				PortalDialog.OnPortalUpdated(portalRecord);
				guid = portalZdoData.Guid;
				Plugin.DebugLog("Startup: refreshed name guid=" + guid.ToString() + ".");
				if (value != null)
				{
					PortalPeerSync.AnnouncePortal(portal.m_uid, portalRecord);
				}
			}
			Guid guid2 = PlayerDestinations.Get(portal.m_uid);
			if (guid2 != Guid.Empty && guid2 != portalZdoData.Guid)
			{
				ScheduleStartupCheck(guid2, portalZdoData.DestinationPosition, Records.ContainsKey(guid2));
			}
			string[] obj2 = new string[5] { "Startup: confirmed guid=", null, null, null, null };
			guid = portalZdoData.Guid;
			obj2[1] = guid.ToString();
			obj2[2] = " route=";
			guid = guid2;
			obj2[3] = guid.ToString();
			obj2[4] = ".";
			Plugin.DebugLog(string.Concat(obj2));
		}

		private unsafe static void ScheduleStartupCheck(Guid guid, Vector3 position, bool known)
		{
			//IL_0026: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			if (guid != Guid.Empty && StartupScheduled.Add(guid))
			{
				StartupQueue.Enqueue(new StartupEntry(guid, position, known));
				string[] obj = new string[9] { "Startup: queued guid=", null, null, null, null, null, null, null, null };
				Guid guid2 = guid;
				obj[1] = guid2.ToString();
				obj[2] = " known=";
				obj[3] = known.ToString();
				obj[4] = " near=";
				Vector3 val = position;
				obj[5] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString();
				obj[6] = " pending=";
				obj[7] = StartupQueue.Count.ToString();
				obj[8] = ".";
				Plugin.DebugLog(string.Concat(obj));
			}
		}

		internal static void QueueStartupCandidate(Guid guid, Vector3 position)
		{
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_startupSession != (Object)(object)ZNet.instance || (Object)(object)_player == (Object)null || (!_startupStarted && !_startupCompleted))
			{
				Guid guid2 = guid;
				Plugin.DebugLog("Startup: ignored peer guid=" + guid2.ToString() + " because catalog check is not ready.");
			}
			else if (Records.ContainsKey(guid) || RemovedIds.Contains(guid) || StartupScheduled.Contains(guid) || StartupScheduled.Count >= 2048)
			{
				string[] obj = new string[11]
				{
					"Startup: ignored peer guid=", null, null, null, null, null, null, null, null, null,
					null
				};
				Guid guid2 = guid;
				obj[1] = guid2.ToString();
				obj[2] = " known=";
				obj[3] = Records.ContainsKey(guid).ToString();
				obj[4] = " removed=";
				obj[5] = RemovedIds.Contains(guid).ToString();
				obj[6] = " queued=";
				obj[7] = StartupScheduled.Contains(guid).ToString();
				obj[8] = " limit=";
				obj[9] = (StartupScheduled.Count >= 2048).ToString();
				obj[10] = ".";
				Plugin.DebugLog(string.Concat(obj));
			}
			else
			{
				ScheduleStartupCheck(guid, position, known: false);
				if (_startupCompleted && StartupQueue.Count > 0)
				{
					Plugin.DebugLog("Startup: resumed check for peer portals.");
					_startupCompleted = false;
					_startupStarted = true;
					_nextStartupCheck = Time.unscaledTime;
				}
			}
		}

		private static void ExpireStartupCheck()
		{
			Guid guid = _startupCurrent.Guid;
			bool flag = _startupCurrent.Known && Records.Remove(guid);
			if (flag)
			{
				PlayerPortalCatalog.Save(_player, _catalogKey, Records);
				PortalDialog.OnPortalRemoved(guid);
				_startupRemoved++;
			}
			string[] obj = new string[9] { "Startup: unanswered guid=", null, null, null, null, null, null, null, null };
			Guid guid2 = guid;
			obj[1] = guid2.ToString();
			obj[2] = " known=";
			bool known = _startupCurrent.Known;
			obj[3] = known.ToString();
			obj[4] = " syncs=";
			obj[5] = _startupCurrent.Syncs.ToString();
			obj[6] = " removed=";
			obj[7] = flag.ToString();
			obj[8] = ".";
			Plugin.DebugLog(string.Concat(obj));
		}

		private static void ReleaseStartupCheck()
		{
			_startupCurrent = null;
			_startupChecked++;
			_nextStartupCheck = Time.unscaledTime + 0.25f;
		}

		private static void FinishStartupCleanup()
		{
			_startupStarted = false;
			_startupCompleted = true;
			Plugin.DebugLog("Startup: complete checked=" + _startupChecked + " removed=" + _startupRemoved + ".");
		}

		internal static void OnUnresponsive(Guid destination, ZDOID origin)
		{
			//IL_001f: 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)
			LoadSession();
			if ((Object)(object)_player == (Object)null || destination == Guid.Empty)
			{
				return;
			}
			PortalZdoData portalZdoData = PortalFields.Read(origin);
			if (portalZdoData != null && !(portalZdoData.DestinationGuid != destination))
			{
				PlayerDestinations.ClearUnresponsive(origin, destination);
				bool flag = Records.Remove(destination);
				if (flag)
				{
					PlayerPortalCatalog.Save(_player, _catalogKey, Records);
					PortalDialog.OnPortalRemoved(destination);
				}
				PortalConnection.StopWaiting(destination);
				((Character)_player).Message((MessageType)2, flag ? "Destination portal did not respond and was removed from your list." : "Destination portal did not respond.", 0, (Sprite)null, false);
				string[] obj = new string[5] { "Catalog: unresponsive guid=", null, null, null, null };
				Guid guid = destination;
				obj[1] = guid.ToString();
				obj[2] = " removed=";
				obj[3] = flag.ToString();
				obj[4] = ".";
				Plugin.DebugLog(string.Concat(obj));
			}
		}
	}
	internal sealed class PortalRecord
	{
		internal Guid Guid;

		internal string LastKnownName;

		internal Vector3 Position;

		internal Biome Biome;
	}
	internal static class PortalVanillaImport
	{
		internal unsafe static bool TryImport(ZDO portal, PortalRecord source)
		{
			//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_0038: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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)
			if (portal == null || source == null)
			{
				return false;
			}
			ZDOID connectionZDOID = portal.GetConnectionZDOID((ConnectionType)1);
			PortalRecord portalRecord = null;
			ZDO val = null;
			if (connectionZDOID != ZDOID.None && PortalFields.Read(portal).DestinationGuid == Guid.Empty)
			{
				val = PortalConnection.GetTarget(connectionZDOID);
				if (val != null)
				{
					PortalFields.EnsureIdentity(connectionZDOID);
				}
				portalRecord = PortalDirectory.CreateRecord(val);
				if (portalRecord == null)
				{
					PortalConnection.Request(connectionZDOID);
				}
			}
			if (!PlayerPortalNames.ImportFromShared(portal, source, portalRecord))
			{
				return false;
			}
			bool flag = false;
			if (portalRecord != null && source.Guid != portalRecord.Guid && Named(portal) && Named(val))
			{
				if (!PortalFields.Claim(portal.m_uid) || !PortalFields.SetDestination(portal.m_uid, portalRecord.Guid, portalRecord.Position))
				{
					return false;
				}
				flag = true;
			}
			string[] obj = new string[7] { "Vanilla import: zdo=", null, null, null, null, null, null };
			ZDOID uid = portal.m_uid;
			obj[1] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
			obj[2] = " partner=";
			obj[3] = ((val == null) ? "none" : ((object)Unsafe.As<ZDOID, ZDOID>(ref val.m_uid)/*cast due to .constrained prefix*/).ToString());
			obj[4] = " routeImported=";
			obj[5] = flag.ToString();
			obj[6] = ".";
			Plugin.DebugLog(string.Concat(obj));
			return true;
		}

		private static bool Named(ZDO portal)
		{
			if (portal != null)
			{
				if (string.IsNullOrWhiteSpace(PortalFields.Read(portal).Name))
				{
					return !string.IsNullOrWhiteSpace(portal.GetString(ZDOVars.s_tag, ""));
				}
				return true;
			}
			return false;
		}
	}
	[BepInPlugin("Landoria.PortalSelector", "PortalSelector", "1.0.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "Landoria.PortalSelector";

		public const string PluginName = "PortalSelector";

		public const string PluginVersion = "1.0.1";

		private static ManualLogSource _logger;

		private Harmony _harmony;

		internal static void DebugLog(string message)
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogDebug((object)message);
			}
		}

		internal static void WarningLog(string message)
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogWarning((object)message);
			}
		}

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			_logger = ((BaseUnityPlugin)this).Logger;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"PortalSelector 1.0.1 loaded.");
			_harmony = new Harmony("Landoria.PortalSelector");
			_harmony.PatchAll();
			Game.m_playerInitialSpawn += PortalDirectory.BeginStartupCleanup;
		}

		private void Update()
		{
			PortalPeerSync.Update();
			PortalDirectory.Update();
		}

		private void OnDestroy()
		{
			Game.m_playerInitialSpawn -= PortalDirectory.BeginStartupCleanup;
			PortalDirectory.ResetStartupCleanup();
			PortalPeerSync.Reset();
			PortalConnection.Reset();
			PlayerDestinations.Reset();
			PortalNameConfirmPatch.Dispose();
			PortalDialog.Close();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_logger = null;
		}
	}
	internal static class PlayerDestinations
	{
		private static readonly Dictionary<ZDOID, string> LastResolution = new Dictionary<ZDOID, string>();

		private static readonly Dictionary<ZDOID, Guid> SuppressedRoutes = new Dictionary<ZDOID, Guid>();

		internal static void Reset()
		{
			LastResolution.Clear();
			SuppressedRoutes.Clear();
		}

		internal static Guid Get(ZDOID origin)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_004e: 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)
			if (PortalDirectory.Find(origin) == null || !PlayerPortalNames.IsNamed(origin))
			{
				return Guid.Empty;
			}
			PortalZdoData portalZdoData = PortalFields.Read(origin);
			Guid guid = portalZdoData?.DestinationGuid ?? Guid.Empty;
			if (guid == Guid.Empty || guid == portalZdoData.Guid || (SuppressedRoutes.TryGetValue(origin, out var value) && value == guid))
			{
				Trace(origin, "no selection");
				return Guid.Empty;
			}
			Guid guid2 = guid;
			Trace(origin, "target=" + guid2);
			return guid;
		}

		internal unsafe static bool Set(ZDOID origin, Guid destination)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0047: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			PortalRecord portalRecord = PortalDirectory.Find(origin);
			PortalRecord portalRecord2 = PortalDirectory.Find(destination);
			if (portalRecord == null || portalRecord2 == null || portalRecord.Guid == destination || !PlayerPortalNames.IsNamed(origin) || string.IsNullOrWhiteSpace(portalRecord2.LastKnownName) || !PortalFields.Claim(origin) || !PlayerPortalNames.EnsureStored(origin) || !PortalFields.SetDestination(origin, destination, portalRecord2.Position))
			{
				return false;
			}
			string[] obj = new string[5] { "Route: saved on source zdo=", null, null, null, null };
			ZDOID val = origin;
			obj[1] = ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString();
			obj[2] = " targetGuid=";
			Guid guid = destination;
			obj[3] = guid.ToString();
			obj[4] = ".";
			Plugin.DebugLog(string.Concat(obj));
			SuppressedRoutes.Remove(origin);
			return true;
		}

		internal static void ClearUnresponsive(ZDOID origin, Guid destination)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0035: 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)
			PortalZdoData portalZdoData = PortalFields.Read(origin);
			if (portalZdoData != null && !(portalZdoData.DestinationGuid != destination))
			{
				SuppressedRoutes[origin] = destination;
				if (PortalFields.Claim(origin) && PortalFields.SetDestination(origin, Guid.Empty, Vector3.zero))
				{
					SuppressedRoutes.Remove(origin);
				}
				LastResolution.Remove(origin);
			}
		}

		internal static void ForgetPortal(Guid destroyed)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			if (ZDOMan.instance != null)
			{
				foreach (ZDO portal in ZDOMan.instance.GetPortalList())
				{
					if (portal.IsOwner() && PortalFields.Read(portal).DestinationGuid == destroyed && PortalFields.SetDestination(portal.m_uid, Guid.Empty, Vector3.zero))
					{
						num++;
					}
				}
			}
			LastResolution.Clear();
			if (num > 0)
			{
				string[] obj = new string[5]
				{
					"Route: cleared ",
					num.ToString(),
					" local routes to destroyed guid=",
					null,
					null
				};
				Guid guid = destroyed;
				obj[3] = guid.ToString();
				obj[4] = ".";
				Plugin.DebugLog(string.Concat(obj));
			}
		}

		private unsafe static void Trace(ZDOID source, string state)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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)
			if (!LastResolution.TryGetValue(source, out var value) || !(value == state))
			{
				LastResolution[source] = state;
				string[] obj = new string[5] { "Route: source=", null, null, null, null };
				ZDOID val = source;
				obj[1] = ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString();
				obj[2] = " ";
				obj[3] = state;
				obj[4] = ".";
				Plugin.DebugLog(string.Concat(obj));
			}
		}
	}
	internal static class PlayerPortalNames
	{
		internal const int MaxLength = 50;

		internal const string DuplicateNameMessage = "This name is already used by another portal.";

		internal static string Get(ZDOID id)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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)
			PortalRecord portalRecord = PortalDirectory.Find(id);
			ZDO target = PortalConnection.GetTarget(id);
			string text = PortalFields.Read(target)?.Name;
			if (!string.IsNullOrWhiteSpace(text))
			{
				if (portalRecord != null && portalRecord.LastKnownName != text)
				{
					PortalDirectory.CacheName(id, text);
				}
				return text;
			}
			if (!string.IsNullOrWhiteSpace(portalRecord?.LastKnownName))
			{
				return portalRecord.LastKnownName;
			}
			return ((target != null) ? target.GetString(ZDOVars.s_tag, "") : null) ?? "";
		}

		internal static string Get(Guid guid)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			PortalRecord portalRecord = PortalDirectory.Find(guid);
			if (portalRecord == null)
			{
				return "";
			}
			ZDO val = PortalConnection.FindLoaded(guid);
			if (val != null)
			{
				return Get(val.m_uid);
			}
			return portalRecord.LastKnownName ?? "";
		}

		internal static bool IsNamed(ZDOID id)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return !string.IsNullOrWhiteSpace(Get(id));
		}

		internal unsafe static bool Set(ZDOID id, string name)
		{
			//IL_001c: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null || PortalConnection.GetTarget(id) == null)
			{
				return false;
			}
			string text = name?.Trim() ?? "";
			if (text.Length > 50)
			{
				text = text.Substring(0, 50);
			}
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			if (InUse(id, text))
			{
				((Character)localPlayer).Message((MessageType)2, "This name is already used by another portal.", 0, (Sprite)null, false);
				return false;
			}
			if (!PortalFields.Claim(id) || !PortalFields.SetName(id, text))
			{
				((Character)localPlayer).Message((MessageType)2, "Could not save the portal name.", 0, (Sprite)null, false);
				return false;
			}
			PortalDirectory.CacheName(id, text);
			ZDOID val = id;
			Plugin.DebugLog("Name: saved on zdo=" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString() + ".");
			return true;
		}

		internal static bool NameExists(ZDOID id, string name)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)ZNet.instance != (Object)null && PortalConnection.GetTarget(id) != null)
			{
				return InUse(id, name?.Trim() ?? "");
			}
			return false;
		}

		internal static bool EnsureStored(ZDOID id)
		{
			//IL_0000: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrWhiteSpace(PortalFields.Read(id)?.Name))
			{
				return true;
			}
			string text = Get(id).Trim();
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			if (InUse(id, text))
			{
				Guid own = PortalDirectory.Find(id)?.Guid ?? Guid.Empty;
				HashSet<string> used = new HashSet<string>(from other in PortalDirectory.KnownRecords()
					where other.Guid != own
					select Get(other.Guid), StringComparer.OrdinalIgnoreCase);
				text = UniqueName(text, used);
			}
			if (!PortalFields.SetName(id, text))
			{
				return false;
			}
			PortalDirectory.CacheName(id, text);
			return true;
		}

		internal static bool ImportFromShared(ZDO portal, PortalRecord record, PortalRecord partner)
		{
			//IL_0013: 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_0046: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			if (portal == null)
			{
				return false;
			}
			ZDOID uid = portal.m_uid;
			string text = portal.GetString(ZDOVars.s_tag, "");
			if (string.IsNullOrWhiteSpace(text) || !string.IsNullOrWhiteSpace(PortalFields.Read(portal).Name))
			{
				return true;
			}
			if (!PortalFields.Claim(uid))
			{
				return false;
			}
			string text2 = InitialName(record, partner, text);
			if (InUse(uid, text2))
			{
				HashSet<string> used = new HashSet<string>(from other in PortalDirectory.KnownRecords()
					where other.Guid != record.Guid
					select Get(other.Guid), StringComparer.OrdinalIgnoreCase);
				text2 = UniqueName(text2, used);
			}
			if (!PortalFields.SetName(uid, text2))
			{
				return false;
			}
			PortalDirectory.CacheName(uid, text2);
			return true;
		}

		private static string InitialName(PortalRecord record, PortalRecord partner, string tag)
		{
			string text = "";
			if (partner != null)
			{
				float num = PortalDirectory.NearestOtherPortalDistanceSquared(record, partner);
				float num2 = PortalDirectory.NearestOtherPortalDistanceSquared(partner, record);
				bool flag = num < 10000f;
				bool flag2 = num2 < 10000f;
				text = (((flag != flag2) ? flag : ((flag && num != num2) ? (num < num2) : (!IsFirst(record, partner)))) ? "_2" : "");
			}
			tag = tag.Trim();
			int num3 = 50 - text.Length;
			if (tag.Length <= num3)
			{
				return tag + text;
			}
			return tag.Substring(0, num3) + text;
		}

		private static bool InUse(ZDOID id, string name)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			Guid own = PortalDirectory.Find(id)?.Guid ?? Guid.Empty;
			if (!string.IsNullOrWhiteSpace(name))
			{
				return PortalDirectory.KnownRecords().Any((PortalRecord other) => other.Guid != own && string.Equals(Get(other.Guid), name, StringComparison.OrdinalIgnoreCase));
			}
			return false;
		}

		private static string UniqueName(string proposed, HashSet<string> used)
		{
			int num = 2;
			string text2;
			while (true)
			{
				string text = " (" + num + ")";
				text2 = proposed.Substring(0, Math.Min(proposed.Length, 50 - text.Length)).TrimEnd(Array.Empty<char>()) + text;
				if (!used.Contains(text2))
				{
					break;
				}
				num++;
			}
			return text2;
		}

		private static bool IsFirst(PortalRecord record, PortalRecord partner)
		{
			return record.Guid.CompareTo(partner.Guid) < 0;
		}
	}
	internal static class PortalConnection
	{
		private static readonly Dictionary<ZDOID, float> Requests = new Dictionary<ZDOID, float>();

		private static readonly HashSet<ZDOID> TrackedRequests = new HashSet<ZDOID>();

		private static Guid _interestGuid;

		private static Vector3 _interestPosition;

		private static float _interestStarted;

		private static float _interestUntil;

		private static int _interestSyncs;

		private const float ResponseTimeout = 5f;

		internal static void Reset()
		{
			Requests.Clear();
			TrackedRequests.Clear();
			_interestGuid = Guid.Empty;
			_interestSyncs = 0;
		}

		internal static ZDO GetTarget(ZDOID id)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ZDOMan instance = ZDOMan.instance;
			ZDO val = ((instance != null) ? instance.GetZDO(id) : null);
			if (val == null || (Object)(object)Game.instance == (Object)null || !Game.instance.PortalPrefabHash.Contains(val.GetPrefab()))
			{
				return null;
			}
			return val;
		}

		internal unsafe static ZDO GetConfirmedTarget(ZDOID id)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			ZDO target = GetTarget(id);
			if (target == null)
			{
				return null;
			}
			if (TrackedRequests.Remove(id))
			{
				ZDOID val = id;
				Plugin.DebugLog("ZDO: received portal zdo=" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString() + ".");
			}
			return target;
		}

		internal static ZDO FindLoaded(Guid guid)
		{
			if (guid == Guid.Empty || ZDOMan.instance == null)
			{
				return null;
			}
			foreach (ZDO portal in ZDOMan.instance.GetPortalList())
			{
				if (PortalFields.Read(portal).Guid == guid)
				{
					return portal;
				}
			}
			return null;
		}

		internal unsafe static ZDO GetConfirmedTarget(Guid guid, Vector3 position, bool focus = true)
		{
			//IL_0087: 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)
			if (guid == Guid.Empty)
			{
				return null;
			}
			ZDO val = FindLoaded(guid);
			if (val != null)
			{
				if (_interestGuid == guid)
				{
					_interestGuid = Guid.Empty;
					string[] obj = new string[5] { "ZDO: resolved guid=", null, null, null, null };
					Guid guid2 = guid;
					obj[1] = guid2.ToString();
					obj[2] = " zdo=";
					ZDOID uid = val.m_uid;
					obj[3] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
					obj[4] = ".";
					Plugin.DebugLog(string.Concat(obj));
				}
				return val;
			}
			if (focus)
			{
				Focus(guid, position);
			}
			return null;
		}

		internal static bool TargetFound(Guid guid, Vector3 position, bool focus)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return GetConfirmedTarget(guid, position, focus) != null;
		}

		internal static bool TryGetInterest(out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			position = _interestPosition;
			if (_interestGuid != Guid.Empty)
			{
				return Time.unscaledTime <= _interestUntil;
			}
			return false;
		}

		internal static void MarkInterestSent()
		{
			_interestSyncs++;
		}

		internal static bool TimedOut(Guid guid, Vector3 position)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (guid != Guid.Empty && _interestGuid == guid && _interestPosition == position && (((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) || _interestSyncs >= 2))
			{
				return Time.unscaledTime - _interestStarted >= 5f;
			}
			return false;
		}

		internal static void StopWaiting(Guid guid)
		{
			if (_interestGuid == guid)
			{
				_interestGuid = Guid.Empty;
				_interestSyncs = 0;
			}
		}

		private unsafe static void Focus(Guid guid, Vector3 position)
		{
			//IL_0060: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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)
			if (_interestGuid != guid || _interestPosition != position || Time.unscaledTime > _interestUntil)
			{
				_interestStarted = Time.unscaledTime;
				_interestSyncs = 0;
				string[] obj = new string[5] { "ZDO: awaiting guid=", null, null, null, null };
				Guid guid2 = guid;
				obj[1] = guid2.ToString();
				obj[2] = " near=";
				Vector3 val = position;
				obj[3] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString();
				obj[4] = ".";
				Plugin.DebugLog(string.Concat(obj));
			}
			_interestGuid = guid;
			_interestPosition = position;
			_interestUntil = Time.unscaledTime + 2f;
		}

		internal unsafe static void Request(ZDOID id)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_0076: 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)
			if (!(id == ZDOID.None) && ZDOMan.instance != null && ZRoutedRpc.instance != null && GetConfirmedTarget(id) == null && (!Requests.TryGetValue(id, out var value) || !(Time.unscaledTime - value < 0.5f)))
			{
				Requests[id] = Time.unscaledTime;
				if (TrackedRequests.Add(id))
				{
					ZDO target = GetTarget(id);
					string[] obj = new string[5] { "ZDO: request zdo=", null, null, null, null };
					ZDOID val = id;
					obj[1] = ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString();
					obj[2] = " local=";
					obj[3] = ((target == null) ? "missing" : "available");
					obj[4] = ".";
					Plugin.DebugLog(string.Concat(obj));
				}
				ZDOMan.instance.RequestZDO(id);
			}
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class PortalCost
	{
		internal const float CostMultiplier = 2f;

		[HarmonyPostfix]
		private static void OnSceneReady()
		{
			PortalConnection.Reset();
			Apply();
		}

		internal static void Apply()
		{
			ZNetScene instance = ZNetScene.instance;
			GameObject obj = ((instance != null) ? instance.GetPrefab("portal_wood") : null);
			Piece val = ((obj != null) ? obj.GetComponent<Piece>() : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Requirement[] resources = val.m_resources;
			foreach (Requirement val2 in resources)
			{
				ItemDrop resItem = val2.m_resItem;
				int num = ((resItem != null) ? ((Object)((Component)resItem).gameObject).name : null) switch
				{
					"SurtlingCore" => 2, 
					"GreydwarfEye" => 10, 
					"FineWood" => 20, 
					_ => 0, 
				};
				if (num > 0)
				{
					val2.m_amount = Mathf.RoundToInt((float)num * 2f);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ZDOMan), "HandleDestroyedZDO")]
	internal static class PortalDestroyedPatch
	{
		[HarmonyPrefix]
		private static void BeforeDestroy(ZDOMan __instance, ZDOID uid)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PortalDirectory.OnDestroyedZDO(__instance, uid);
		}
	}
	internal static class PortalFields
	{
		internal const string NameKey = "Landoria.PortalSelector.Name";

		internal const string GuidKey = "Landoria.PortalSelector.Guid";

		internal const string DestinationGuidKey = "Landoria.PortalSelector.DestinationGuid";

		internal const string DestinationPositionKey = "Landoria.PortalSelector.DestinationPosition";

		internal const string CreatedAtKey = "Landoria.PortalSelector.CreatedAtUtc";

		internal static PortalZdoData Read(ZDOID id)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Read(PortalConnection.GetTarget(id));
		}

		internal static PortalZdoData Read(ZDO portal)
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			DateTime? createdAtUtc = null;
			if (portal != null && DateTime.TryParse(portal.GetString("Landoria.PortalSelector.CreatedAtUtc", ""), CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var result))
			{
				createdAtUtc = result.ToUniversalTime();
			}
			if (portal == null)
			{
				return null;
			}
			Guid.TryParse(portal.GetString("Landoria.PortalSelector.Guid", ""), out var result2);
			Guid.TryParse(portal.GetString("Landoria.PortalSelector.DestinationGuid", ""), out var result3);
			return new PortalZdoData
			{
				Name = portal.GetString("Landoria.PortalSelector.Name", ""),
				Guid = result2,
				Position = portal.GetPosition(),
				DestinationGuid = result3,
				DestinationPosition = portal.GetVec3("Landoria.PortalSelector.DestinationPosition", Vector3.zero),
				CreatedAtUtc = createdAtUtc
			};
		}

		internal static bool EnsureIdentity(ZDOID id)
		{
			//IL_0000: 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)
			ZDO target = PortalConnection.GetTarget(id);
			if (target == null)
			{
				return false;
			}
			if (Read(target).Guid != Guid.Empty)
			{
				return true;
			}
			if (!Claim(id))
			{
				return false;
			}
			target.Set("Landoria.PortalSelector.Guid", Guid.NewGuid().ToString("D"));
			SetCreatedAt(target);
			ZDOMan.instance.SetDirtyPortals();
			return true;
		}

		private static bool SetCreatedAt(ZDO portal)
		{
			if (portal == null || !portal.IsOwner())
			{
				return false;
			}
			if (!Read(portal).CreatedAtUtc.HasValue)
			{
				portal.Set("Landoria.PortalSelector.CreatedAtUtc", DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture));
				ZDOMan.instance.SetDirtyPortals();
			}
			return true;
		}

		internal static bool Claim(ZDOID id)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			ZDO target = PortalConnection.GetTarget(id);
			if (target == null)
			{
				return false;
			}
			if (!target.IsOwner())
			{
				ZNetScene instance = ZNetScene.instance;
				if (instance != null)
				{
					GameObject obj = instance.FindInstance(id);
					if (obj != null)
					{
						ZNetView component = obj.GetComponent<ZNetView>();
						if (component != null)
						{
							component.ClaimOwnership();
						}
					}
				}
			}
			return target.IsOwner();
		}

		internal static bool SetName(ZDOID id, string name)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			ZDO target = PortalConnection.GetTarget(id);
			if (target == null || !target.IsOwner() || !SetCreatedAt(target))
			{
				return false;
			}
			target.Set("Landoria.PortalSelector.Name", name);
			ZDOMan.instance.SetDirtyPortals();
			return true;
		}

		internal static bool SetDestination(ZDOID id, Guid destination, Vector3 position)
		{
			//IL_0000: 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)
			ZDO target = PortalConnection.GetTarget(id);
			if (target == null || !target.IsOwner() || !SetCreatedAt(target))
			{
				return false;
			}
			target.Set("Landoria.PortalSelector.DestinationGuid", (destination == Guid.Empty) ? "" : destination.ToString("D"));
			target.Set("Landoria.PortalSelector.DestinationPosition", position);
			ZDOMan.instance.SetDirtyPortals();
			return true;
		}
	}
	[HarmonyPatch(typeof(ZNet), "SendServerSyncPlayerData")]
	internal static class PortalInterestPatch
	{
		[HarmonyPrefix]
		private static void BeforeSync(ref Vector3 ___m_referencePosition, out Vector3 __state)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			__state = ___m_referencePosition;
			if (PortalConnection.TryGetInterest(out var position))
			{
				PortalConnection.MarkInterestSent();
				___m_referencePosition = position;
			}
			else if (PortalDirectory.TryGetStartupInterest(out position))
			{
				PortalDirectory.MarkStartupInterestSent();
				___m_referencePosition = position;
			}
		}

		[HarmonyPostfix]
		private static void AfterSync(ref Vector3 ___m_referencePosition, Vector3 __state)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			___m_referencePosition = __state;
		}
	}
	internal static class PortalPeerSync
	{
		private sealed class PortalNotice
		{
			internal readonly long World;

			internal readonly int Kind;

			internal readonly ZDOID Id;

			internal readonly Guid Guid;

			internal readonly string Name;

			internal readonly Vector3 Position;

			internal PortalNotice(long world, int kind, ZDOID id, Guid guid, string name, Vector3 position)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				World = world;
				Kind = kind;
				Id = id;
				Guid = guid;
				Name = name;
				Position = position;
			}
		}

		private const string RpcName = "Landoria.PortalSelector.PortalNoticeV2";

		private const int Format = 2;

		private const int Upsert = 1;

		private const int Remove = 2;

		private const int MaxPending = 256;

		private static readonly Queue<PortalNotice> Pending = new Queue<PortalNotice>();

		private static ZRoutedRpc _registered;

		private static bool _sending;

		private const string SnapshotRequestRpc = "Landoria.PortalSelector.SnapshotRequestV1";

		private const string SnapshotReplyRpc = "Landoria.PortalSelector.SnapshotReplyV1";

		private const int SnapshotFormat = 1;

		private const int SnapshotBatchSize = 48;

		internal static void Update()
		{
			EnsureRegistered();
			if (!((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)ZNet.instance == (Object)null) && WorldGenerator.instance != null)
			{
				while (Pending.Count > 0)
				{
					Apply(Pending.Dequeue());
				}
			}
		}

		internal static void Reset()
		{
			Pending.Clear();
		}

		internal static void AnnouncePortal(ZDOID id, PortalRecord record)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (record != null && record.Guid != Guid.Empty && id != ZDOID.None)
			{
				Publish(1, id, record.Guid, record.LastKnownName, record.Position);
			}
		}

		internal static void AnnounceRemoval(Guid guid)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (guid != Guid.Empty)
			{
				Publish(2, ZDOID.None, guid, "", Vector3.zero);
			}
		}

		private static void EnsureRegistered()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null && instance != _registered)
			{
				instance.Register<ZPackage>("Landoria.PortalSelector.PortalNoticeV2", (Action<long, ZPackage>)Receive);
				instance.Register<ZPackage>("Landoria.PortalSelector.SnapshotRequestV1", (Action<long, ZPackage>)ReceiveSnapshotRequest);
				instance.Register<ZPackage>("Landoria.PortalSelector.SnapshotReplyV1", (Action<long, ZPackage>)ReceiveSnapshotReply);
				_registered = instance;
				Pending.Clear();
			}
		}

		private static void Publish(int kind, ZDOID id, Guid guid, string name, Vector3 position)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0051: 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)
			EnsureRegistered();
			if (!((Object)(object)ZNet.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && _registered == ZRoutedRpc.instance)
			{
				ZPackage val = new ZPackage();
				val.Write(2);
				val.Write(ZNet.instance.GetWorldUID());
				val.Write(kind);
				val.Write(id);
				val.Write(guid.ToString("D"));
				val.Write(name ?? "");
				val.Write(position);
				_sending = true;
				try
				{
					_registered.InvokeRoutedRPC(0L, "Landoria.PortalSelector.PortalNoticeV2", new object[1] { val });
				}
				finally
				{
					_sending = false;
				}
				string[] obj = new string[5]
				{
					"Peer: announced ",
					kind.ToString(),
					" guid=",
					null,
					null
				};
				Guid guid2 = guid;
				obj[3] = guid2.ToString();
				obj[4] = ".";
				Plugin.DebugLog(string.Concat(obj));
			}
		}

		private static void Receive(long sender, ZPackage data)
		{
			if (_sending || data == null || data.GetArray().Length > 512)
			{
				return;
			}
			try
			{
				PortalNotice portalNotice = Read(data);
				if (portalNotice == null)
				{
					return;
				}
				if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null || WorldGenerator.instance == null)
				{
					if (Pending.Count < 256)
					{
						Pending.Enqueue(portalNotice);
					}
				}
				else
				{
					Apply(portalNotice);
				}
			}
			catch (Exception ex)
			{
				Plugin.WarningLog("Peer: invalid portal notice (" + ex.GetType().Name + ").");
			}
		}

		private static PortalNotice Read(ZPackage data)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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)
			if (data.ReadInt() != 2)
			{
				return null;
			}
			long world = data.ReadLong();
			int num = data.ReadInt();
			ZDOID val = data.ReadZDOID();
			string input = data.ReadString();
			string text = data.ReadString();
			Vector3 val2 = data.ReadVector3();
			if ((num != 1 && num != 2) || (num == 1 && val == ZDOID.None) || !Guid.TryParse(input, out var result) || result == Guid.Empty || text.Length > 50 || !Finite(val2.x) || !Finite(val2.y) || !Finite(val2.z))
			{
				return null;
			}
			return new PortalNotice(world, num, val, result, text, val2);
		}

		private static bool Finite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}

		private static void Apply(PortalNotice notice)
		{
			//IL_0043: 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)
			if (!((Object)(object)ZNet.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && ZNet.instance.GetWorldUID() == notice.World)
			{
				if (notice.Kind == 2)
				{
					PortalDirectory.OnPeerRemoval(notice.Guid);
				}
				else
				{
					PortalDirectory.OnPeerPortal(notice.Id, notice.Guid, notice.Name, notice.Position);
				}
			}
		}

		internal static void RequestSnapshot()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			EnsureRegistered();
			if (!((Object)(object)ZNet.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && _registered == ZRoutedRpc.instance)
			{
				ZPackage val = new ZPackage();
				val.Write(1);
				val.Write(ZNet.instance.GetWorldUID());
				Plugin.DebugLog("Peer: join snapshot exchange started.");
				_sending = true;
				try
				{
					_registered.InvokeRoutedRPC(0L, "Landoria.PortalSelector.SnapshotRequestV1", new object[1] { val });
					SendSnapshot(0L);
				}
				finally
				{
					_sending = false;
				}
				Plugin.DebugLog("Peer: exchanged portal snapshots.");
			}
		}

		private static void ReceiveSnapshotRequest(long sender, ZPackage data)
		{
			if (_sending || sender == 0L || data == null || data.GetArray().Length > 32 || (Object)(object)ZNet.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			try
			{
				if (data.ReadInt() == 1 && data.ReadLong() == ZNet.instance.GetWorldUID())
				{
					Plugin.DebugLog("Peer: snapshot requested by peer=" + sender + ".");
					SendSnapshot(sender);
				}
			}
			catch (Exception ex)
			{
				Plugin.WarningLog("Peer: invalid snapshot request (" + ex.GetType().Name + ").");
			}
		}

		private static void SendSnapshot(long recipient)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			List<PortalRecord> list = PortalDirectory.KnownRecords();
			for (int i = 0; i < list.Count; i += 48)
			{
				int num = Math.Min(48, list.Count - i);
				ZPackage val = new ZPackage();
				val.Write(1);
				val.Write(ZNet.instance.GetWorldUID());
				val.Write(num);
				for (int j = i; j < i + num; j++)
				{
					val.Write(list[j].Guid.ToString("D"));
					val.Write(list[j].Position);
				}
				_registered.InvokeRoutedRPC(recipient, "Landoria.PortalSelector.SnapshotReplyV1", new object[1] { val });
				Plugin.DebugLog("Peer: sent snapshot batch peer=" + recipient + " offset=" + i + " count=" + num + ".");
			}
			Plugin.DebugLog("Peer: shared catalog peer=" + recipient + " total=" + list.Count + ".");
		}

		private static void ReceiveSnapshotReply(long sender, ZPackage data)
		{
			if (_sending || sender == 0L || data == null || data.GetArray().Length > 8192 || (Object)(object)ZNet.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			try
			{
				if (data.ReadInt() == 1 && data.ReadLong() == ZNet.instance.GetWorldUID())
				{
					int num = data.ReadInt();
					if (num >= 0 && num <= 48)
					{
						Plugin.DebugLog("Peer: received snapshot batch peer=" + sender + " count=" + num + ".");
						QueueSnapshotEntries(data, num);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.WarningLog("Peer: invalid snapshot reply (" + ex.GetType().Name + ").");
			}
		}

		private static void QueueSnapshotEntries(ZPackage data, int count)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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)
			for (int i = 0; i < count; i++)
			{
				string input = data.ReadString();
				Vector3 val = data.ReadVector3();
				if (Guid.TryParse(input, out var result) && result != Guid.Empty && Finite(val.x) && Finite(val.y) && Finite(val.z))
				{
					PortalDirectory.QueueStartupCandidate(result, val);
				}
				else
				{
					Plugin.DebugLog("Peer: ignored invalid snapshot entry=" + i + ".");
				}
			}
		}
	}
	internal sealed class PortalZdoData
	{
		internal string Name;

		internal Guid Guid;

		internal Vector3 Position;

		internal Guid DestinationGuid;

		internal Vector3 DestinationPosition;

		internal DateTime? CreatedAtUtc;
	}
	[HarmonyPatch]
	internal static class PortalCameraScrollPatch
	{
		private static bool _readingCameraScroll;

		[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
		[HarmonyPrefix]
		private static void BeforeCamera()
		{
			_readingCameraScroll = PortalDialog.IsOpen;
		}

		[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
		[HarmonyPostfix]
		private static void AfterCamera()
		{
			_readingCameraScroll = false;
		}

		[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
		[HarmonyPrefix]
		private static bool CameraWheel(ref float __result)
		{
			if (!_readingCameraScroll)
			{
				return true;
			}
			__result = 0f;
			return false;
		}
	}
	[HarmonyPatch]
	internal static class PortalDialog
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__ToggleMenu;

			public static UnityAction <1>__HideMenu;
		}

		private static TextInput _owner;

		private static GameObject _originalPanel;

		private static TMP_Text _originalTopic;

		private static GuiInputField _originalInput;

		private static GameObject _panel;

		private static TMP_Text _topic;

		private static GuiInputField _input;

		private static Button _choiceButton;

		private static GameObject _menu;

		private static GameObject _menuBlocker;

		private static ZDOID _origin;

		private static Guid _originGuid;

		private static Guid _selected;

		private static List<PortalRecord> _options;

		private const float PickerHeightIncrease = 16f;

		private const float ExtraDialogHeight = 32f;

		private const float TitleSpacing = 2f;

		private const float ActionSpacing = 12f;

		private const float MenuHeight = 260f;

		private const float RowHeight = 36f;

		private const float ScrollbarWidth = 18f;

		internal static bool IsOpen
		{
			get
			{
				if ((Object)(object)_owner != (Object)null && (Object)(object)_panel != (Object)null && (Object)(object)_owner.m_panel == (Object)(object)_panel)
				{
					return _panel.activeInHierarchy;
				}
				return false;
			}
		}

		internal static void Open(ZDOID origin, List<PortalRecord> records)
		{
			//IL_0007: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			PortalRecord source = PortalDirectory.Find(origin);
			if ((Object)(object)TextInput.instance == (Object)null || source == null || !records.Any((PortalRecord r) => r.Guid == source.Guid && Available(r)))
			{
				return;
			}
			_origin = origin;
			_originGuid = source.Guid;
			_options = (from r in records
				where r.Guid != source.Guid && Available(r)
				orderby BiomeOrder(r.Biome), r.Position.x * r.Position.x + r.Position.z * r.Position.z
				select r).ThenBy<PortalRecord, string>((PortalRecord r) => PortalDisplay.Name(r.Guid), StringComparer.CurrentCultureIgnoreCase).ToList();
			_selected = PlayerDestinations.Get(origin);
			if (_options.Count == 0)
			{
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, "No known destinations yet.", 0, (Sprite)null, false);
				}
			}
			else
			{
				TextInput.instance.RequestText((TextReceiver)(object)new PortalSelectionReceiver(), "Choose destination", 0);
				RefreshChoice();
			}
		}

		private unsafe static int BiomeOrder(Biome biome)
		{
			return ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString() switch
			{
				"Meadows" => 0, 
				"BlackForest" => 1, 
				"Swamp" => 2, 
				"Mountain" => 3, 
				"Plains" => 4, 
				"Mistlands" => 5, 
				"AshLands" => 6, 
				"DeepNorth" => 7, 
				"Ocean" => 8, 
				_ => 9, 
			};
		}

		internal static void Confirm()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (!(_selected != Guid.Empty) || _options == null || !_options.Exists((PortalRecord record) => record.Guid == _selected && Available(record)))
			{
				return;
			}
			if (PlayerDestinations.Set(_origin, _selected))
			{
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)1, "Portal destination selected.", 0, (Sprite)null, false);
				}
			}
			else
			{
				Player localPlayer2 = Player.m_localPlayer;
				if (localPlayer2 != null)
				{
					((Character)localPlayer2).Message((MessageType)2, "Could not save the portal destination.", 0, (Sprite)null, false);
				}
			}
		}

		internal static void OnPortalRemoved(Guid guid)
		{
			if (_originGuid == guid && IsOpen)
			{
				HideMenu();
				_owner.Hide();
			}
			else
			{
				if (_options == null || _options.RemoveAll((PortalRecord record) => record.Guid == guid) == 0)
				{
					return;
				}
				if (_selected == guid)
				{
					_selected = Guid.Empty;
				}
				RefreshChoice();
				if (IsOpen && (Object)(object)_menu != (Object)null && _menu.activeSelf)
				{
					if (_options.Count == 0)
					{
						HideMenu();
					}
					else
					{
						PopulateMenu();
					}
				}
			}
		}

		internal static void OnPortalUpdated(PortalRecord record)
		{
			if (!IsOpen || _options == null || record.Guid == _originGuid)
			{
				return;
			}
			_options.RemoveAll((PortalRecord option) => option.Guid == record.Guid);
			if (!string.IsNullOrWhiteSpace(record.LastKnownName))
			{
				_options.Add(record);
			}
			_options = (from option in _options
				orderby BiomeOrder(option.Biome), option.Position.x * option.Position.x + option.Position.z * option.Position.z
				select option).ThenBy<PortalRecord, string>((PortalRecord option) => PortalDisplay.Name(option.Guid), StringComparer.CurrentCultureIgnoreCase).ToList();
			RefreshChoice();
			if ((Object)(object)_menu != (Object)null && _menu.activeSelf)
			{
				if (_options.Count == 0)
				{
					HideMenu();
				}
				else
				{
					PopulateMenu();
				}
			}
		}

		private static bool Available(PortalRecord option)
		{
			return PortalDirectory.Find(option.Guid) != null;
		}

		internal static void Close()
		{
			if ((Object)(object)_owner != (Object)null && (Object)(object)_originalPanel != (Object)null)
			{
				_owner.m_panel = _originalPanel;
				_owner.m_topic = _originalTopic;
				_owner.m_inputField = _originalInput;
			}
			if ((Object)(object)_panel != (Object)null)
			{
				Object.Destroy((Object)(object)_panel);
			}
			_panel = null;
			_menu = null;
			_menuBlocker = null;
			_owner = null;
		}

		[HarmonyPatch(typeof(TextInput), "RequestText")]
		[HarmonyPrefix]
		[HarmonyAfter(new string[] { "Landoria.NearbyStorage" })]
		private static void BeforeRequest(TextInput __instance, TextReceiver sign)
		{
			bool flag = sign is PortalSelectionReceiver;
			if (!flag && ((Object)(object)_owner != (Object)(object)__instance || (Object)(object)__instance.m_panel != (Object)(object)_panel))
			{
				return;
			}
			if (flag && (Object)(object)_owner != (Object)(object)__instance)
			{
				Reset(__instance);
			}
			if (flag && (Object)(object)_panel == (Object)null)
			{
				Create();
			}
			if (!((Object)(object)_panel == (Object)null))
			{
				if (__instance.m_panel.activeSelf)
				{
					__instance.Hide();
				}
				__instance.m_panel = (flag ? _panel : _originalPanel);
				__instance.m_topic = (flag ? _topic : _originalTopic);
				__instance.m_inputField = (flag ? _input : _originalInput);
				if (flag)
				{
					HideMenu();
				}
			}
		}

		private static void Reset(TextInput owner)
		{
			Close();
			_owner = owner;
			_originalPanel = owner.m_panel;
			_originalTopic = owner.m_topic;
			_originalInput = owner.m_inputField;
		}

		private static void Create()
		{
			if (!((Object)(object)_originalPanel == (Object)null) && !((Object)(object)_originalTopic == (Object)null) && !((Object)(object)_originalInput == (Object)null))
			{
				_panel = Object.Instantiate<GameObject>(_originalPanel, _originalPanel.transform.parent);
				((Object)_panel).name = "PortalSelectorDialog";
				_panel.SetActive(false);
				Transform obj = CopyControl(_originalTopic.transform);
				_topic = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
				Transform obj2 = CopyControl(((Component)_originalInput).transform);
				_input = ((obj2 != null) ? ((Component)obj2).GetComponent<GuiInputField>() : null);
				if ((Object)(object)_topic == (Object)null || (Object)(object)_input == (Object)null)
				{
					Object.Destroy((Object)(object)_panel);
					_panel = null;
				}
				else
				{
					SpaceDialogVertically();
					CreatePicker();
				}
			}
		}

		private static void SpaceDialogVertically()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = _panel.transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if (!((Object)(object)val == (Object)null))
			{
				Rect rect = val.rect;
				val.SetSizeWithCurrentAnchors((Axis)1, ((Rect)(ref rect)).height + 32f);
				Transform transform2 = _topic.transform;
				transform2.position += ((Transform)val).TransformVector(new Vector3(0f, 2f, 0f));
				Button[] componentsInChildren = ((Component)val).GetComponentsInChildren<Button>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Transform transform3 = ((Component)componentsInChildren[i]).transform;
					transform3.position += ((Transform)val).TransformVector(new Vector3(0f, -12f, 0f));
				}
			}
		}

		private static Transform CopyControl(Transform source)
		{
			string text = ((Object)source).name;
			Transform parent = source.parent;
			while ((Object)(object)parent != (Object)(object)_originalPanel.transform)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return _panel.transform.Find(text);
		}

		private static void CreatePicker()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_00a1: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//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_00ef: Expected O, but got Unknown
			Transform transform = ((Component)_input).transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			Button componentInChildren = _panel.GetComponentInChildren<Button>(true);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)componentInChildren == (Object)null))
			{
				GameObject obj = Object.Instantiate<GameObject>(((Component)componentInChildren).gameObject, ((Transform)val).parent, false);
				((Object)obj).name = "DestinationPicker";
				Transform transform2 = obj.transform;
				RectTransform val2 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
				val2.anchorMin = val.anchorMin;
				val2.anchorMax = val.anchorMax;
				val2.offsetMin = val.offsetMin - new Vector2(0f, 8f);
				val2.offsetMax = val.offsetMax + new Vector2(0f, 8f);
				_choiceButton = obj.GetComponent<Button>();
				_choiceButton.onClick = new ButtonClickedEvent();
				ButtonClickedEvent onClick = _choiceButton.onClick;
				object obj2 = <>O.<0>__ToggleMenu;
				if (obj2 == null)
				{
					UnityAction val3 = ToggleMenu;
					<>O.<0>__ToggleMenu = val3;
					obj2 = (object)val3;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj2);
				obj.SetActive(true);
				((Component)_input).gameObject.SetActive(false);
				CreateMenu(val2);
			}
		}

		private static void RefreshChoice()
		{
			if (!((Object)(object)_choiceButton == (Object)null))
			{
				PortalRecord portalRecord = _options?.Find((PortalRecord item) => item.Guid == _selected && Available(item));
				string text = ((portalRecord == null) ? "Select a portal" : ChoiceLabel(portalRecord));
				TMP_Text[] componentsInChildren = ((Component)_choiceButton).GetComponentsInChildren<TMP_Text>(true);
				foreach (TMP_Text obj in componentsInChildren)
				{
					obj.text = text;
					obj.enableAutoSizing = true;
					obj.fontSize = 20f;
					obj.fontSizeMin = 16f;
					obj.fontSizeMax = 20f;
				}
			}
		}

		private static void ToggleMenu()
		{
			if ((Object)(object)_menu == (Object)null)
			{
				return;
			}
			bool flag = !_menu.activeSelf;
			if (flag)
			{
				_options.RemoveAll((PortalRecord record) => !Available(record));
				if (_options.Count == 0)
				{
					Player localPlayer = Player.m_localPlayer;
					if (localPlayer != null)
					{
						((Character)localPlayer).Message((MessageType)2, "No known destinations available.", 0, (Sprite)null, false);
					}
					return;
				}
				PopulateMenu();
				_menu.transform.SetAsLastSibling();
			}
			_menuBlocker.SetActive(flag);
			_menu.SetActive(flag);
		}

		private static void HideMenu()
		{
			if ((Object)(object)_menu != (Object)null)
			{
				_menu.SetActive(false);
			}
			if ((Object)(object)_menuBlocker != (Object)null)
			{
				_menuBlocker.SetActive(false);
			}
		}

		private static void CreateBlocker(RectTransform panel)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_004f: 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)
			//IL_008b: Expected O, but got Unknown
			RectTransform obj = Rect("Destination click blocker", (Transform)(object)panel, new Vector2(10000f, 10000f));
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 0.5f);
			obj.anchorMax = val;
			obj.anchorMin = val;
			obj.anchoredPosition = Vector2.zero;
			((Graphic)((Component)obj).gameObject.AddComponent<Image>()).color = Color.clear;
			Button obj2 = ((Component)obj).gameObject.AddComponent<Button>();
			((Selectable)obj2).transition = (Transition)0;
			ButtonClickedEvent onClick = obj2.onClick;
			object obj3 = <>O.<1>__HideMenu;
			if (obj3 == null)
			{
				UnityAction val2 = HideMenu;
				<>O.<1>__HideMenu = val2;
				obj3 = (object)val2;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj3);
			_menuBlocker = ((Component)obj).gameObject;
			_menuBlocker.SetActive(false);
		}

		private static void CreateMenu(RectTransform button)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = _panel.transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			CreateBlocker(val);
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			button.GetWorldCorners(array);
			Vector3 val2 = ((Transform)val).InverseTransformPoint(array[0]);
			Vector3 val3 = ((Transform)val).InverseTransformPoint(array[3]);
			RectTransform val4 = Rect("Portal destinations", (Transform)(object)val, new Vector2(val3.x - val2.x, 260f));
			Vector2 val5 = default(Vector2);
			((Vector2)(ref val5))..ctor(0.5f, 0.5f);
			val4.anchorMax = val5;
			val4.anchorMin = val5;
			val4.pivot = new Vector2(0f, 1f);
			val4.anchoredPosition = new Vector2(val2.x, val2.y);
			((Graphic)((Component)val4).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.98f);
			RectTransform val6 = Rect("Viewport", (Transform)(object)val4, Vector2.zero);
			val6.anchorMin = Vector2.zero;
			val6.anchorMax = Vector2.one;
			val6.offsetMin = Vector2.zero;
			val6.offsetMax = new Vector2(-18f, 0f);
			((Component)val6).gameObject.AddComponent<RectMask2D>();
			RectTransform val7 = Rect("Content", (Transform)(object)val6, Vector2.zero);
			((Vector2)(ref val5))..ctor(0f, 1f);
			val7.anchorMax = val5;
			val7.anchorMin = val5;
			val7.pivot = new Vector2(0f, 1f);
			ScrollRect val8 = ((Component)val4).gameObject.AddComponent<ScrollRect>();
			val8.viewport = val6;
			val8.content = val7;
			val8.horizontal = false;
			val8.movementType = (MovementType)2;
			val8.scrollSensitivity = 800f;
			CreateScrollbar(val4, val8);
			_menu = ((Component)val4).gameObject;
			_menu.SetActive(false);
		}

		private static void CreateScrollbar(RectTransform root, ScrollRect scroll)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = Rect("Scrollbar", (Transform)(object)root, Vector2.zero);
			val.anchorMin = new Vector2(1f, 0f);
			val.anchorMax = Vector2.one;
			val.offsetMin = new Vector2(-18f, 0f);
			val.offsetMax = Vector2.zero;
			RectTransform val2 = Rect("Handle", (Transform)(object)val, Vector2.zero);
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			Vector2 offsetMin = (val2.offsetMax = Vector2.zero);
			val2.offsetMin = offsetMin;
			Image val3 = ((Component)val2).gameObject.AddComponent<Image>();
			((Graphic)val3).color = new Color(1f, 0.68f, 0.3f, 0.85f);
			Scrollbar val4 = ((Component)val).gameObject.AddComponent<Scrollbar>();
			val4.handleRect = val2;
			((Selectable)val4).targetGraphic = (Graphic)(object)val3;
			val4.direction = (Direction)2;
			scroll.verticalScrollbar = val4;
		}

		private static void PopulateMenu()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_0103: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = _menu.transform.Find("Viewport/Content");
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			Transform transform = _menu.transform;
			Rect rect = ((RectTransform)((transform is RectTransform) ? transform : null)).rect;
			float num = ((Rect)(ref rect)).width - 18f;
			for (int num2 = ((Transform)val).childCount - 1; num2 >= 0; num2--)
			{
				Object.Destroy((Object)(object)((Component)((Transform)val).GetChild(num2)).gameObject);
			}
			int num3 = 0;
			Biome? val2 = null;
			foreach (PortalRecord option in _options)
			{
				if