Decompiled source of UnifiedTargetPortal v1.0.0

plugins/UnifiedTargetPortal/UnifiedTargetPortal.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Splatform;
using TMPro;
using UnifiedTargetPortal.Features;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 UnifiedTargetPortal
{
	[BepInPlugin("com.xman0922.unifiedtargetportal", "Unified Target Portal", "1.0.0")]
	[BepInIncompatibility("org.bepinex.plugins.targetportal")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.xman0922.unifiedtargetportal";

		public const string PluginName = "Unified Target Portal";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		private Harmony? harmony;

		private PortalFeature? feature;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			harmony = new Harmony("com.xman0922.unifiedtargetportal");
			feature = new PortalFeature(((BaseUnityPlugin)this).Config);
			feature.Initialize(harmony);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Unified Target Portal 1.0.0 loaded.");
		}

		private void Update()
		{
			feature?.Update();
		}

		private void OnDestroy()
		{
			feature?.Shutdown();
			Harmony? obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
}
namespace UnifiedTargetPortal.Features
{
	internal interface IFeatureModule
	{
		void Initialize(Harmony harmony);

		void DrawGui();

		void Shutdown();
	}
	internal interface IUpdatableFeature
	{
		void Update();
	}
	internal static class Loc
	{
		internal static bool IsKorean
		{
			get
			{
				Localization instance = Localization.instance;
				if (instance != null)
				{
					return string.Equals(instance.GetSelectedLanguage(), "Korean", StringComparison.OrdinalIgnoreCase);
				}
				return false;
			}
		}

		internal static string Text(string korean, string english)
		{
			if (!IsKorean)
			{
				return english;
			}
			return korean;
		}
	}
	internal sealed class PortalFeature : IFeatureModule, IUpdatableFeature
	{
		private enum PortalMode
		{
			Public,
			Private
		}

		private enum ItemRestrictionMode
		{
			Never,
			Default,
			Always
		}

		private sealed class PortalEntry
		{
			internal ZDOID Id;

			internal string Tag = string.Empty;

			internal Vector3 Position;

			internal Quaternion Rotation;

			internal PortalMode Mode;

			internal string OwnerId = string.Empty;

			internal string OwnerName = string.Empty;
		}

		private sealed class FavoritePortalClick : MonoBehaviour, IPointerClickHandler, IEventSystemHandler
		{
			internal PortalFeature Owner;

			internal PortalEntry Portal;

			public void OnPointerClick(PointerEventData eventData)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Invalid comparison between Unknown and I4
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				if ((int)eventData.button == 1)
				{
					Owner.ToggleFavorite(Portal);
				}
				else if ((int)eventData.button == 0)
				{
					Owner.Travel(Portal);
				}
			}
		}

		private const string ListRpc = "VU_PortalList";

		private const string RequestRpc = "VU_PortalRequest";

		private const string ChangeModeRpc = "VU_PortalMode";

		private const string ModeKey = "TargetPortal PortalMode";

		private const string OwnerIdKey = "TargetPortal PortalOwnerId";

		private const string OwnerNameKey = "TargetPortal PortalOwnerName";

		private const string FavoritesKey = "TargetPortal Favorites";

		private static PortalFeature? current;

		private static readonly MethodInfo? ScreenToWorldMethod = AccessTools.Method(typeof(Minimap), "ScreenToWorldPoint", (Type[])null, (Type[])null);

		private static readonly MethodInfo? InteractRadiusGetter = AccessTools.PropertyGetter(typeof(Minimap), "PinInteractRadius");

		private readonly ConfigEntry<bool> enabled;

		private readonly ConfigEntry<float> broadcastInterval;

		private readonly ConfigEntry<bool> showUntagged;

		private readonly ConfigEntry<bool> allowPrivatePortals;

		private readonly ConfigEntry<KeyboardShortcut> modeToggleShortcut;

		private readonly ConfigEntry<KeyboardShortcut> mapPinsShortcut;

		private readonly ConfigEntry<bool> showPlayerPinsDuringPortal;

		private readonly ConfigEntry<bool> allowMapPinToggleWhenClosed;

		private readonly ConfigEntry<int> portalNameLength;

		private readonly ConfigEntry<int> maximumNumberOfPortals;

		private readonly ConfigEntry<ItemRestrictionMode> itemRestrictionMode;

		private readonly ConfigEntry<PortalMode> defaultPortalMode;

		private readonly List<PortalEntry> portals = new List<PortalEntry>();

		private readonly List<PinData> pickerPins = new List<PinData>();

		private readonly Dictionary<PinData, PortalEntry> pinToPortal = new Dictionary<PinData, PortalEntry>();

		private readonly List<PinData> persistentPins = new List<PinData>();

		private TeleportWorld? pickerSource;

		private ConfigEntry<bool> openMapOnEnter;

		private ConfigEntry<bool> portalAnimation;

		private ConfigEntry<bool> hidePinsDuringPortal;

		private bool[]? savedIconTypes;

		private static readonly FieldInfo? VisibleIconTypesField = AccessTools.Field(typeof(Minimap), "m_visibleIconTypes");

		private static readonly FieldInfo? PinUpdateRequiredField = AccessTools.Field(typeof(Minimap), "m_pinUpdateRequired");

		private static readonly FieldInfo? PlacementGhostField = AccessTools.Field(typeof(Player), "m_placementGhost");

		private GameObject? favoriteList;

		private bool rpcRegistered;

		private bool showPortalPins;

		private float nextBroadcast;

		private int lastBroadcastHash;

		private static readonly FieldInfo? TriggerPortalField = AccessTools.Field(typeof(TeleportWorldTrigger), "m_teleportWorld");

		private static bool Active => current?.enabled.Value ?? false;

		internal PortalFeature(ConfigFile config)
		{
			//IL_00bc: 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_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Expected O, but got Unknown
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Expected O, but got Unknown
			enabled = config.Bind<bool>("Portals", "Enabled", true, "Choose a destination on the map when using a portal. Hold Use to rename instead.");
			broadcastInterval = config.Bind<float>("Portals", "BroadcastInterval", 5f, "Seconds between server checks for portal changes.");
			showUntagged = config.Bind<bool>("Portals", "ShowUntagged", true, "List portals that have no tag.");
			allowPrivatePortals = config.Bind<bool>("Portals", "AllowPrivatePortals", true, "Allow portal owners to switch between Public and Private with Shift + Use.");
			modeToggleShortcut = config.Bind<KeyboardShortcut>("Portals", "ModeToggleShortcut", new KeyboardShortcut((KeyCode)304, Array.Empty<KeyCode>()), "Modifier held while using a portal to switch its visibility mode.");
			mapPinsShortcut = config.Bind<KeyboardShortcut>("Portals", "MapPinsShortcut", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Show or hide portal pins while the large map is open. F8 avoids Valheim 1.0's P-to-ping binding.");
			openMapOnEnter = config.Bind<bool>("Portals", "OpenMapOnEnter", true, "Walk into a portal to open the destination map, like TargetPortal. Off: press Use to open it instead.");
			portalAnimation = config.Bind<bool>("Portals", "PortalAnimation", true, "Show the active portal swirl on every portal, since any portal can now reach any other.");
			hidePinsDuringPortal = config.Bind<bool>("Portals", "HidePinsDuringPortal", true, "Hide other map pins while choosing a destination, so only portals are visible.");
			showPlayerPinsDuringPortal = config.Bind<bool>("Portals", "ShowPlayerPinsDuringPortal", true, "Keep live player pins visible while choosing a destination, matching TargetPortal.");
			allowMapPinToggleWhenClosed = config.Bind<bool>("Portals", "AllowMapPinToggleWhenClosed", false, "Allow the portal-pin hotkey while the small map is active, matching TargetPortal's optional setting.");
			portalNameLength = config.Bind<int>("Portals", "PortalNameLength", 10, new ConfigDescription("Maximum portal-name length.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 100), Array.Empty<object>()));
			maximumNumberOfPortals = config.Bind<int>("Portals", "MaximumNumberOfPortals", 0, new ConfigDescription("Maximum portals allowed in the world. 0 means unlimited.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10000), Array.Empty<object>()));
			itemRestrictionMode = config.Bind<ItemRestrictionMode>("Portals", "IgnoreItemTeleportRestrictions", ItemRestrictionMode.Default, "Never: enforce restrictions for every portal. Default: use the portal's vanilla rule. Always: ignore restrictions.");
			defaultPortalMode = config.Bind<PortalMode>("Portals", "DefaultPortalMode", PortalMode.Private, "Visibility mode assigned to newly built portals.");
		}

		public void Initialize(Harmony harmony)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Expected O, but got Unknown
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Expected O, but got Unknown
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Expected O, but got Unknown
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Expected O, but got Unknown
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Expected O, but got Unknown
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Expected O, but got Unknown
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Expected O, but got Unknown
			current = this;
			harmony.Patch((MethodBase)AccessTools.Method(typeof(TeleportWorld), "Interact", (Type[])null, (Type[])null), new HarmonyMethod(typeof(PortalFeature), "InteractPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(TeleportWorld), "GetHoverText", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(PortalFeature), "HoverTextPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(TeleportWorld), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(PortalFeature), "PortalAwakePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Piece), "SetCreator", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(PortalFeature), "PieceSetCreatorPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Minimap), "OnMapLeftClick", (Type[])null, (Type[])null), new HarmonyMethod(typeof(PortalFeature), "MapLeftClickPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Minimap), "RemovePinUnderPointer", (Type[])null, (Type[])null), new HarmonyMethod(typeof(PortalFeature), "RemovePinUnderPointerPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Minimap), "SetMapMode", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(PortalFeature), "SetMapModePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Game), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(PortalFeature), "GameStartPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(TeleportWorldTrigger), "OnTriggerEnter", (Type[])null, (Type[])null), new HarmonyMethod(typeof(PortalFeature), "TriggerEnterPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(TeleportWorldTrigger), "OnTriggerExit", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(PortalFeature), "TriggerExitPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "PlacePiece", (Type[])null, (Type[])null), new HarmonyMethod(typeof(PortalFeature), "PlacePiecePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(TeleportWorld), "HaveTarget", (Type[])null, (Type[])null), new HarmonyMethod(typeof(PortalFeature), "HaveTargetPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(TeleportWorld), "TargetFound", (Type[])null, (Type[])null), new HarmonyMethod(typeof(PortalFeature), "TargetFoundPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			string[] array = new string[2] { "OnMapDblClick", "OnMapMiddleClick" };
			foreach (string text in array)
			{
				MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(Minimap), text, (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(PortalFeature), "BlockWhilePickingPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			Plugin.Log.LogInfo((object)("PortalFeature: " + (enabled.Value ? ("enabled, open on " + (openMapOnEnter.Value ? "enter" : "use")) : "disabled") + "."));
		}

		private static void GameStartPostfix()
		{
			current?.RegisterRpcs();
		}

		private void RegisterRpcs()
		{
			if (!rpcRegistered && ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.Register<ZPackage>("VU_PortalList", (Action<long, ZPackage>)OnPortalList);
				ZRoutedRpc.instance.Register("VU_PortalRequest", (Action<long>)OnPortalRequest);
				ZRoutedRpc.instance.Register<ZDOID, int, string, string>("VU_PortalMode", (Method<ZDOID, int, string, string>)OnPortalModeChange);
				rpcRegistered = true;
				lastBroadcastHash = 0;
				nextBroadcast = 0f;
				portals.Clear();
				if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer())
				{
					ZRoutedRpc.instance.InvokeRoutedRPC("VU_PortalRequest", Array.Empty<object>());
				}
			}
		}

		public void Update()
		{
			UpdateMapControls();
			if (Active && rpcRegistered && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && ZDOMan.instance != null && !(Time.time < nextBroadcast))
			{
				nextBroadcast = Time.time + Mathf.Max(1f, broadcastInterval.Value);
				int hash;
				ZPackage package = BuildPackage(out hash);
				if (hash != lastBroadcastHash)
				{
					lastBroadcastHash = hash;
					Broadcast(package, 0L);
				}
			}
		}

		private void OnPortalRequest(long sender)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				Broadcast(BuildPackage(out var _), sender);
			}
		}

		private void Broadcast(ZPackage package, long target)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC(target, "VU_PortalList", new object[1] { package });
			if (target == 0L)
			{
				package.SetPos(0);
				OnPortalList(ZNet.GetUID(), package);
			}
		}

		private static ZPackage BuildPackage(out int hash)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			List<ZDO> portalList = ZDOMan.instance.GetPortalList();
			ZPackage val = new ZPackage();
			val.Write(portalList.Count);
			hash = portalList.Count;
			foreach (ZDO item in portalList)
			{
				string text = item.GetString(ZDOVars.s_tag, "");
				Vector3 position = item.GetPosition();
				val.Write(item.m_uid);
				val.Write(text);
				val.Write(position);
				val.Write(item.GetRotation());
				PortalMode portalMode = SquashMode(item.GetInt("TargetPortal PortalMode", 0));
				string text2 = item.GetString("TargetPortal PortalOwnerId", string.Empty);
				string text3 = item.GetString("TargetPortal PortalOwnerName", string.Empty);
				val.Write((int)portalMode);
				val.Write(text2);
				val.Write(text3);
				hash = hash * 31 + ((object)Unsafe.As<ZDOID, ZDOID>(ref item.m_uid)/*cast due to .constrained prefix*/).GetHashCode();
				hash = hash * 31 + text.GetHashCode();
				hash = hash * 31 + Mathf.RoundToInt(position.x) + Mathf.RoundToInt(position.z) * 977;
				hash = (int)(hash * 31 + portalMode);
				hash = hash * 31 + text2.GetHashCode();
			}
			return val;
		}

		private void OnPortalList(long sender, ZPackage package)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_0047: 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)
			portals.Clear();
			int num = package.ReadInt();
			for (int i = 0; i < num; i++)
			{
				portals.Add(new PortalEntry
				{
					Id = package.ReadZDOID(),
					Tag = package.ReadString(),
					Position = package.ReadVector3(),
					Rotation = package.ReadQuaternion(),
					Mode = SquashMode(package.ReadInt()),
					OwnerId = package.ReadString(),
					OwnerName = package.ReadString()
				});
			}
			if (showPortalPins && (Object)(object)pickerSource == (Object)null)
			{
				RefreshPersistentPins();
			}
		}

		private static bool InteractPrefix(TeleportWorld __instance, Humanoid human, bool hold, ref bool __result)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Expected O, but got Unknown
			if (!Active || current == null || (Object)(object)human != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			if (!PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, true, false))
			{
				((Character)human).Message((MessageType)2, "$piece_noaccess", 0, (Sprite)null, false);
				__result = true;
				return false;
			}
			if (!hold && current.allowPrivatePortals.Value)
			{
				KeyboardShortcut value = current.modeToggleShortcut.Value;
				if (((KeyboardShortcut)(ref value)).IsPressed())
				{
					current.TogglePortalMode(__instance, human);
					__result = true;
					return false;
				}
			}
			if (current.openMapOnEnter.Value)
			{
				if (hold)
				{
					__result = false;
					return false;
				}
				if (!CanModifyPortal(__instance, showMessage: true))
				{
					__result = true;
					return false;
				}
				if (!TextInput.IsVisible() && (Object)(object)TextInput.instance != (Object)null)
				{
					TextInput.instance.RequestText((TextReceiver)(object)__instance, "$piece_portal_tag", Mathf.Clamp(current.portalNameLength.Value, 5, 100));
				}
				__result = true;
				return false;
			}
			if (hold)
			{
				if (!CanModifyPortal(__instance, showMessage: true))
				{
					__result = true;
					return false;
				}
				if (!TextInput.IsVisible() && (Object)(object)TextInput.instance != (Object)null)
				{
					TextInput.instance.RequestText((TextReceiver)(object)__instance, "$piece_portal_tag", Mathf.Clamp(current.portalNameLength.Value, 5, 100));
				}
				__result = true;
				return false;
			}
			current.OpenPicker(__instance, (Player)human, fromTrigger: false);
			__result = true;
			return false;
		}

		private static bool TriggerEnterPrefix(TeleportWorldTrigger __instance, Collider colliderIn)
		{
			if (!Active || current == null || !current.openMapOnEnter.Value)
			{
				return true;
			}
			Player component = ((Component)colliderIn).GetComponent<Player>();
			if ((Object)(object)component == (Object)null || (Object)(object)component != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			if (((Character)component).IsTeleporting() || (Object)(object)current.pickerSource != (Object)null)
			{
				return false;
			}
			object? obj = TriggerPortalField?.GetValue(__instance);
			TeleportWorld val = (TeleportWorld)((obj is TeleportWorld) ? obj : null);
			if (val != null)
			{
				current.OpenPicker(val, component, fromTrigger: true);
			}
			return false;
		}

		private static void TriggerExitPostfix(TeleportWorldTrigger __instance, Collider colliderIn)
		{
			if (!Active || (Object)(object)current?.pickerSource == (Object)null || (Object)(object)((Component)colliderIn).GetComponent<Player>() != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			object? obj = TriggerPortalField?.GetValue(__instance);
			TeleportWorld val = (TeleportWorld)((obj is TeleportWorld) ? obj : null);
			if (val != null && val == current.pickerSource)
			{
				if ((Object)(object)Minimap.instance != (Object)null)
				{
					Minimap.instance.m_dragView = false;
				}
				current.ClosePicker();
			}
		}

		private static bool PlacePiecePrefix(Player __instance)
		{
			if (Active && current != null && current.maximumNumberOfPortals.Value > 0)
			{
				object? obj = PlacementGhostField?.GetValue(__instance);
				GameObject val = (GameObject)((obj is GameObject) ? obj : null);
				if (val != null && !((Object)(object)val.GetComponent<TeleportWorld>() == (Object)null) && current.portals.Count >= current.maximumNumberOfPortals.Value)
				{
					((Character)__instance).Message((MessageType)2, Loc.Text($"이 월드에는 포털을 {current.maximumNumberOfPortals.Value}개보다 더 설치할 수 없습니다.", $"You cannot place more than {current.maximumNumberOfPortals.Value} portals in this world."), 0, (Sprite)null, false);
					return false;
				}
			}
			return true;
		}

		private static bool HaveTargetPrefix(ref bool __result)
		{
			if (!Active)
			{
				return true;
			}
			__result = true;
			return false;
		}

		private static bool TargetFoundPrefix(ref bool __result)
		{
			if (!Active || current == null)
			{
				return true;
			}
			__result = current.portalAnimation.Value;
			return false;
		}

		private static bool BlockWhilePickingPrefix()
		{
			if (current != null)
			{
				return (Object)(object)current.pickerSource == (Object)null;
			}
			return true;
		}

		private static void HoverTextPostfix(TeleportWorld __instance, ref string __result)
		{
			if (!Active)
			{
				return;
			}
			int num = __result.LastIndexOf('\n');
			string text = ((num >= 0) ? __result.Substring(0, num) : __result);
			string text2 = Localization.instance.Localize("$KEY_Use");
			PortalFeature? portalFeature = current;
			if (portalFeature != null && portalFeature.openMapOnEnter.Value)
			{
				__result = text + "\n" + Loc.Text("포털에 들어가면 목적지를 선택합니다", "Walk in to choose a destination") + "\n" + Loc.Text("[<color=yellow><b>" + text2 + "</b></color>] 이름 변경", "[<color=yellow><b>" + text2 + "</b></color>] Rename");
			}
			else
			{
				__result = text + "\n" + Loc.Text("[<color=yellow><b>" + text2 + "</b></color>] 목적지 선택", "[<color=yellow><b>" + text2 + "</b></color>] Choose destination") + "\n" + Loc.Text("[<color=yellow><b>" + text2 + "</b></color> 길게] 이름 변경", "[Hold <color=yellow><b>" + text2 + "</b></color>] Rename");
			}
			PortalFeature? portalFeature2 = current;
			if (portalFeature2 != null && portalFeature2.allowPrivatePortals.Value)
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				ZDO obj = ((component != null) ? component.GetZDO() : null);
				PortalMode portalMode = SquashMode((obj != null) ? obj.GetInt("TargetPortal PortalMode", 0) : 0);
				string text3 = ((obj != null) ? obj.GetString("TargetPortal PortalOwnerName", string.Empty) : null) ?? string.Empty;
				string text4 = ModeText(portalMode);
				if (portalMode == PortalMode.Private && !string.IsNullOrEmpty(text3))
				{
					text4 += Loc.Text(" (소유자: " + StringExtensionMethods.RemoveRichTextTags(text3) + ")", " (Owner: " + StringExtensionMethods.RemoveRichTextTags(text3) + ")");
				}
				__result = __result + "\n" + Loc.Text("공개 범위: " + text4, "Visibility: " + text4) + "\n" + Loc.Text("[<color=yellow><b>Shift + " + text2 + "</b></color>] 공개/비공개 전환", "[<color=yellow><b>Shift + " + text2 + "</b></color>] Toggle public/private");
			}
		}

		private static void PortalAwakePostfix(TeleportWorld __instance)
		{
			if (!Active)
			{
				return;
			}
			PortalFeature? portalFeature = current;
			if (portalFeature != null && portalFeature.allowPrivatePortals.Value && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				ZDO val = ((component != null) ? component.GetZDO() : null);
				Piece component2 = ((Component)__instance).GetComponent<Piece>();
				if (val != null && !((Object)(object)component2 == (Object)null) && val.GetInt("TargetPortal PortalMode", -1) == -1 && component2.GetCreator() == Player.m_localPlayer.GetPlayerID())
				{
					SetMode(val, current.defaultPortalMode.Value, LocalOwnerId(), Player.m_localPlayer.GetPlayerName());
				}
			}
		}

		private static void PieceSetCreatorPostfix(Piece __instance)
		{
			if (!Active)
			{
				return;
			}
			PortalFeature? portalFeature = current;
			if (portalFeature == null || !portalFeature.allowPrivatePortals.Value || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)((Component)__instance).GetComponent<TeleportWorld>() == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			ZDO val = ((component != null) ? component.GetZDO() : null);
			if (val != null && val.GetInt("TargetPortal PortalMode", -1) == -1 && __instance.GetCreator() == Player.m_localPlayer.GetPlayerID())
			{
				SetMode(val, current.defaultPortalMode.Value, LocalOwnerId(), Player.m_localPlayer.GetPlayerName());
				if (current != null)
				{
					current.nextBroadcast = 0f;
				}
			}
		}

		private void TogglePortalMode(TeleportWorld portal, Humanoid human)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if (CanModifyPortal(portal, showMessage: true))
			{
				ZNetView component = ((Component)portal).GetComponent<ZNetView>();
				ZDO val = ((component != null) ? component.GetZDO() : null);
				if (val != null && ZRoutedRpc.instance != null)
				{
					PortalMode portalMode = ((SquashMode(val.GetInt("TargetPortal PortalMode", 0)) == PortalMode.Public) ? PortalMode.Private : PortalMode.Public);
					Player localPlayer = Player.m_localPlayer;
					string text = ((localPlayer != null) ? localPlayer.GetPlayerName() : null) ?? ((Character)human).GetHoverName();
					ZRoutedRpc.instance.InvokeRoutedRPC(0L, "VU_PortalMode", new object[4]
					{
						val.m_uid,
						(int)portalMode,
						LocalOwnerId(),
						text
					});
					SetMode(val, portalMode, LocalOwnerId(), text);
					((Character)human).Message((MessageType)2, Loc.Text("포털을 " + ModeText(portalMode) + " 모드로 변경했습니다.", "Portal changed to " + ModeText(portalMode) + " mode."), 0, (Sprite)null, false);
					nextBroadcast = 0f;
				}
			}
		}

		private void OnPortalModeChange(long sender, ZDOID portalId, int rawMode, string ownerId, string ownerName)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ZDOMan instance = ZDOMan.instance;
			ZDO val = ((instance != null) ? instance.GetZDO(portalId) : null);
			if (val != null)
			{
				SetMode(val, SquashMode(rawMode), ownerId, ownerName);
				nextBroadcast = 0f;
			}
		}

		private static void SetMode(ZDO zdo, PortalMode mode, string ownerId, string ownerName)
		{
			zdo.Set("TargetPortal PortalMode", (int)mode);
			zdo.Set("TargetPortal PortalOwnerId", ownerId);
			zdo.Set("TargetPortal PortalOwnerName", ownerName);
		}

		private static bool CanModifyPortal(TeleportWorld portal, bool showMessage)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (PrivateArea.CheckAccess(((Component)portal).transform.position, 0f, true, false))
			{
				return true;
			}
			if (showMessage)
			{
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, "$piece_noaccess", 0, (Sprite)null, false);
				}
			}
			return false;
		}

		private static PortalMode SquashMode(int rawMode)
		{
			if (rawMode != 0)
			{
				return PortalMode.Private;
			}
			return PortalMode.Public;
		}

		private static string LocalOwnerId()
		{
			//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)
			return ((object)((IUser)PlatformManager.DistributionPlatform.LocalUser).PlatformUserID/*cast due to .constrained prefix*/).ToString().Replace("Steam_", string.Empty);
		}

		private static string ModeText(PortalMode mode)
		{
			if (mode != PortalMode.Public)
			{
				return Loc.Text("비공개", "Private");
			}
			return Loc.Text("공개", "Public");
		}

		private void OpenPicker(TeleportWorld source, Player player, bool fromTrigger)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			if (ZoneSystem.instance.GetGlobalKey((GlobalKeys)32))
			{
				((Character)player).Message((MessageType)2, "$msg_blocked", 0, (Sprite)null, false);
				return;
			}
			if (!CanTeleport(player, source))
			{
				((Character)player).Message((MessageType)2, "$msg_noteleport", 0, (Sprite)null, false);
				return;
			}
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			ClearPersistentPins();
			ClearPickerPins();
			ZNetView component = ((Component)source).GetComponent<ZNetView>();
			ZDOID val = (ZDOID)(((??)((component == null) ? ((ZDOID?)null) : component.GetZDO()?.m_uid)) ?? ZDOID.None);
			int num = 0;
			foreach (PortalEntry portal in portals)
			{
				if (!(portal.Id == val) && (!string.IsNullOrEmpty(portal.Tag) || showUntagged.Value) && (!allowPrivatePortals.Value || portal.Mode != PortalMode.Private || string.Equals(portal.OwnerId, LocalOwnerId(), StringComparison.Ordinal)))
				{
					string text = (string.IsNullOrEmpty(portal.Tag) ? Loc.Text("(이름 없음)", "(untagged)") : StringExtensionMethods.RemoveRichTextTags(portal.Tag));
					PinData val2 = instance.AddPin(portal.Position, (PinType)6, text, false, false, 0L, default(PlatformUserID));
					pickerPins.Add(val2);
					pinToPortal[val2] = portal;
					num++;
				}
			}
			if (num == 0)
			{
				((Character)player).Message((MessageType)2, Loc.Text("이동할 수 있는 다른 포털이 없습니다.", "No other portal to travel to."), 0, (Sprite)null, false);
				ClearPickerPins();
				return;
			}
			pickerSource = source;
			if (InventoryGui.IsVisible())
			{
				InventoryGui.instance.Hide();
			}
			bool noMap = Game.m_noMap;
			Game.m_noMap = false;
			if (fromTrigger)
			{
				instance.ShowPointOnMap(((Component)source).transform.position);
			}
			else
			{
				instance.SetMapMode((MapMode)2);
			}
			Game.m_noMap = noMap;
			HideOtherPins(instance);
			BuildFavoriteList();
			((Character)player).Message((MessageType)2, Loc.Text("포털 클릭: 이동 · 우클릭: 즐겨찾기", "Click: travel · Right-click: favourite"), 0, (Sprite)null, false);
		}

		private static bool MapLeftClickPrefix(Minimap __instance)
		{
			if (current == null || (Object)(object)current.pickerSource == (Object)null || current.pickerPins.Count == 0)
			{
				return true;
			}
			if (!current.TryGetClosestPickerPortal(__instance, out PinData _, out PortalEntry portal))
			{
				return true;
			}
			current.Travel(portal);
			return false;
		}

		private static bool RemovePinUnderPointerPrefix(Minimap __instance)
		{
			if (current == null || (Object)(object)current.pickerSource == (Object)null)
			{
				return true;
			}
			if (!current.TryGetClosestPickerPortal(__instance, out PinData _, out PortalEntry portal))
			{
				return true;
			}
			current.ToggleFavorite(portal);
			return false;
		}

		private bool TryGetClosestPickerPortal(Minimap map, out PinData pin, out PortalEntry portal)
		{
			//IL_0030: 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_0045: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			pin = null;
			portal = null;
			if (ScreenToWorldMethod == null || InteractRadiusGetter == null)
			{
				return false;
			}
			Vector3 val = (Vector3)ScreenToWorldMethod.Invoke(map, new object[1] { ZInput.pointerPosition });
			float num = (float)InteractRadiusGetter.Invoke(map, null);
			float num2 = float.MaxValue;
			foreach (PinData pickerPin in pickerPins)
			{
				float num3 = Utils.DistanceXZ(val, pickerPin.m_pos);
				if (num3 < num && num3 < num2)
				{
					pin = pickerPin;
					num2 = num3;
				}
			}
			if (pin != null)
			{
				return pinToPortal.TryGetValue(pin, out portal);
			}
			return false;
		}

		private HashSet<string> FavoriteIds()
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || !localPlayer.m_customData.TryGetValue("TargetPortal Favorites", out var value))
			{
				return hashSet;
			}
			string[] array = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string item in array)
			{
				hashSet.Add(item);
			}
			return hashSet;
		}

		private void ToggleFavorite(PortalEntry portal)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				HashSet<string> hashSet = FavoriteIds();
				string item = ((object)Unsafe.As<ZDOID, ZDOID>(ref portal.Id)/*cast due to .constrained prefix*/).ToString();
				bool flag = hashSet.Add(item);
				if (!flag)
				{
					hashSet.Remove(item);
				}
				localPlayer.m_customData["TargetPortal Favorites"] = string.Join(",", hashSet);
				BuildFavoriteList();
				((Character)localPlayer).Message((MessageType)2, flag ? Loc.Text("포털을 즐겨찾기에 추가했습니다.", "Portal added to favourites.") : Loc.Text("포털을 즐겨찾기에서 제거했습니다.", "Portal removed from favourites."), 0, (Sprite)null, false);
			}
		}

		private unsafe void BuildFavoriteList()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			DestroyFavoriteList();
			Minimap instance = Minimap.instance;
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null || (Object)(object)pickerSource == (Object)null)
			{
				return;
			}
			Transform obj = instance.m_largeRoot.transform.Find("KeyHints/keyboard_hints/AddPin");
			GameObject val = ((obj != null) ? ((Component)obj).gameObject : null);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Portal favourites: native AddPin key-hint template was not found.");
				return;
			}
			favoriteList = new GameObject("UnifiedTargetPortal Favorites", new Type[2]
			{
				typeof(RectTransform),
				typeof(VerticalLayoutGroup)
			});
			favoriteList.transform.SetParent(instance.m_largeRoot.transform, false);
			RectTransform val2 = (RectTransform)favoriteList.transform;
			val2.anchorMin = new Vector2(0f, 0.5f);
			val2.anchorMax = new Vector2(0f, 0.5f);
			val2.pivot = new Vector2(0f, 0.5f);
			val2.anchoredPosition = new Vector2(15f, 0f);
			val2.sizeDelta = new Vector2(240f, 500f);
			VerticalLayoutGroup component = favoriteList.GetComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)component).spacing = 3f;
			HashSet<string> hashSet = FavoriteIds();
			foreach (KeyValuePair<PinData, PortalEntry> item in pinToPortal)
			{
				PortalEntry value = item.Value;
				if (hashSet.Contains(((object)Unsafe.As<ZDOID, ZDOID>(ref value.Id)/*cast due to .constrained prefix*/).ToString()))
				{
					GameObject obj2 = Object.Instantiate<GameObject>(val, favoriteList.transform, false);
					ZDOID id = value.Id;
					((Object)obj2).name = "FavoritePortal_" + ((object)(*(ZDOID*)(&id))/*cast due to .constrained prefix*/).ToString();
					obj2.SetActive(true);
					HorizontalLayoutGroup component2 = obj2.GetComponent<HorizontalLayoutGroup>();
					if ((Object)(object)component2 != (Object)null)
					{
						((LayoutGroup)component2).childAlignment = (TextAnchor)3;
					}
					Transform obj3 = obj2.transform.Find("Label");
					TMP_Text val3 = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null);
					if ((Object)(object)val3 != (Object)null)
					{
						val3.text = (string.IsNullOrEmpty(value.Tag) ? Loc.Text("(이름 없음)", "(untagged)") : StringExtensionMethods.RemoveRichTextTags(value.Tag));
						val3.transform.SetAsLastSibling();
					}
					Transform obj4 = obj2.transform.Find("keyboard_hint");
					Image val4 = ((obj4 != null) ? ((Component)obj4).GetComponent<Image>() : null);
					if ((Object)(object)val4 != (Object)null)
					{
						val4.sprite = item.Key.m_icon;
					}
					FavoritePortalClick favoritePortalClick = obj2.AddComponent<FavoritePortalClick>();
					favoritePortalClick.Owner = this;
					favoritePortalClick.Portal = value;
				}
			}
		}

		private void UpdateMapControls()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Invalid comparison between Unknown and I4
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Invalid comparison between Unknown and I4
			//IL_006b: 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)
			Minimap instance = Minimap.instance;
			if (!Active || (Object)(object)instance == (Object)null)
			{
				return;
			}
			if ((Object)(object)pickerSource != (Object)null)
			{
				if (showPlayerPinsDuringPortal.Value)
				{
					instance.UpdatePlayerPins(Time.deltaTime);
				}
			}
			else
			{
				if ((int)instance.m_mode != 2 && (!allowMapPinToggleWhenClosed.Value || (int)instance.m_mode <= 0))
				{
					return;
				}
				KeyboardShortcut value = mapPinsShortcut.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					showPortalPins = !showPortalPins;
					if (showPortalPins)
					{
						RefreshPersistentPins();
					}
					else
					{
						ClearPersistentPins();
					}
					Player localPlayer = Player.m_localPlayer;
					if (localPlayer != null)
					{
						((Character)localPlayer).Message((MessageType)2, showPortalPins ? Loc.Text("지도에 포털을 표시합니다.", "Portal pins shown.") : Loc.Text("지도에서 포털을 숨깁니다.", "Portal pins hidden."), 0, (Sprite)null, false);
					}
				}
			}
		}

		private void RefreshPersistentPins()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			ClearPersistentPins();
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			foreach (PortalEntry portal in portals)
			{
				if ((!string.IsNullOrEmpty(portal.Tag) || showUntagged.Value) && (!allowPrivatePortals.Value || portal.Mode != PortalMode.Private || string.Equals(portal.OwnerId, LocalOwnerId(), StringComparison.Ordinal)))
				{
					string text = (string.IsNullOrEmpty(portal.Tag) ? Loc.Text("(이름 없음)", "(untagged)") : StringExtensionMethods.RemoveRichTextTags(portal.Tag));
					persistentPins.Add(instance.AddPin(portal.Position, (PinType)6, text, false, false, 0L, default(PlatformUserID)));
				}
			}
		}

		private void ClearPersistentPins()
		{
			Minimap instance = Minimap.instance;
			foreach (PinData persistentPin in persistentPins)
			{
				if (instance != null)
				{
					instance.RemovePin(persistentPin);
				}
			}
			persistentPins.Clear();
		}

		private void Travel(PortalEntry destination)
		{
			//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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			TeleportWorld val = pickerSource;
			ClosePicker();
			if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)val == (Object)null))
			{
				if (ZoneSystem.instance.GetGlobalKey((GlobalKeys)32))
				{
					((Character)localPlayer).Message((MessageType)2, "$msg_blocked", 0, (Sprite)null, false);
					return;
				}
				float num = default(float);
				if (ZoneSystem.instance.GetGlobalKey((GlobalKeys)33) && (RandEventSystem.instance.GetBossEvent() != null || (ZoneSystem.instance.GetGlobalKey((GlobalKeys)47, ref num) && num > 0f)))
				{
					((Character)localPlayer).Message((MessageType)2, "$msg_blockedbyboss", 0, (Sprite)null, false);
					return;
				}
				if (!CanTeleport(localPlayer, val))
				{
					((Character)localPlayer).Message((MessageType)2, "$msg_noteleport", 0, (Sprite)null, false);
					return;
				}
				Vector3 val2 = destination.Rotation * Vector3.forward;
				Vector3 val3 = destination.Position + val2 * val.m_exitDistance + Vector3.up;
				Plugin.Log.LogInfo((object)$"Portal travel to '{destination.Tag}' at {destination.Position}.");
				((Character)localPlayer).TeleportTo(val3, destination.Rotation, true);
				Game.instance.IncrementPlayerStat((PlayerStatType)15, 1f, false);
			}
		}

		private static void SetMapModePostfix(MapMode mode)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			if (current != null && (Object)(object)current.pickerSource != (Object)null && (int)mode != 2)
			{
				current.ClosePicker();
			}
		}

		private void HideOtherPins(Minimap map)
		{
			//IL_007c: 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_0083: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected I4, but got Unknown
			if (!hidePinsDuringPortal.Value || savedIconTypes != null || !(VisibleIconTypesField?.GetValue(map) is bool[] array))
			{
				return;
			}
			savedIconTypes = (bool[])array.Clone();
			HashSet<int> hashSet = new HashSet<int> { 6 };
			if (showPlayerPinsDuringPortal.Value)
			{
				hashSet.Add(10);
			}
			HashSet<Sprite> hashSet2 = new HashSet<Sprite>();
			foreach (LocationSpriteData locationIcon in map.m_locationIcons)
			{
				if ((Object)(object)locationIcon.m_icon != (Object)null)
				{
					hashSet2.Add(locationIcon.m_icon);
				}
			}
			foreach (PinData pin in map.m_pins)
			{
				if ((Object)(object)pin.m_icon != (Object)null && hashSet2.Contains(pin.m_icon))
				{
					hashSet.Add((int)pin.m_type);
				}
			}
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = hashSet.Contains(i);
			}
			PinUpdateRequiredField?.SetValue(map, true);
		}

		private bool CanTeleport(Player player, TeleportWorld source)
		{
			if (itemRestrictionMode.Value != ItemRestrictionMode.Always)
			{
				return ((Humanoid)player).IsTeleportable(itemRestrictionMode.Value == ItemRestrictionMode.Default && source.m_allowAllItems);
			}
			return true;
		}

		private void RestorePins()
		{
			Minimap instance = Minimap.instance;
			if (savedIconTypes == null || (Object)(object)instance == (Object)null || !(VisibleIconTypesField?.GetValue(instance) is bool[] array))
			{
				savedIconTypes = null;
				return;
			}
			Array.Copy(savedIconTypes, array, Math.Min(savedIconTypes.Length, array.Length));
			savedIconTypes = null;
			PinUpdateRequiredField?.SetValue(instance, true);
		}

		private void ClosePicker()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Invalid comparison between Unknown and I4
			bool num = (Object)(object)pickerSource != (Object)null;
			pickerSource = null;
			RestorePins();
			ClearPickerPins();
			if (num && (Object)(object)Minimap.instance != (Object)null && (int)Minimap.instance.m_mode == 2)
			{
				Minimap.instance.SetMapMode((MapMode)1);
			}
			if (showPortalPins)
			{
				RefreshPersistentPins();
			}
		}

		private void ClearPickerPins()
		{
			Minimap instance = Minimap.instance;
			foreach (PinData pickerPin in pickerPins)
			{
				if ((Object)(object)instance != (Object)null)
				{
					instance.RemovePin(pickerPin);
				}
			}
			pickerPins.Clear();
			pinToPortal.Clear();
			DestroyFavoriteList();
		}

		private void DestroyFavoriteList()
		{
			if ((Object)(object)favoriteList != (Object)null)
			{
				Object.Destroy((Object)(object)favoriteList);
				favoriteList = null;
			}
		}

		public void DrawGui()
		{
		}

		public void Shutdown()
		{
			ClosePicker();
			ClearPersistentPins();
			portals.Clear();
			current = null;
		}
	}
}