Decompiled source of WaypointPortals v1.3.0

WaypointPortals/WaypointPortals.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Splatform;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("WaypointPortals")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WaypointPortals")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("6e33aa45-7019-47eb-a399-eb2c3206efec")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace WaypointPortals;

[BepInPlugin("nb.wackjob.waypoint-portals", "Waypoint Portals", "1.3.0")]
public class WaypointPortalsPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "nb.wackjob.waypoint-portals";

	public const string PluginName = "Waypoint Portals";

	public const string PluginVersion = "1.3.0";

	internal static ManualLogSource Log;

	internal static Harmony Harmony;

	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("nb.wackjob.waypoint-portals");
		Harmony.PatchAll();
		Log.LogInfo((object)"Waypoint Portals 1.3.0 loaded");
	}

	private void Update()
	{
		if (!((Object)(object)ZNet.instance == (Object)null) && ZRoutedRpc.instance != null)
		{
			if (ZNet.instance.IsServer())
			{
				WaypointPortalsServer.InitServer();
				WaypointPortalsServer.Maintenance();
				WPState.Maintenance();
			}
			else
			{
				WPState.Maintenance();
				WaypointPortalsClient.Maintenance();
			}
		}
	}

	private void OnDestroy()
	{
		Harmony harmony = Harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}
}
internal static class MapApi
{
	private static MethodInfo _setMapMode;

	private static MethodInfo _screenToWorld;

	private static Type _mapModeEnum;

	private static void Ensure()
	{
		if (_setMapMode == null)
		{
			_setMapMode = AccessTools.Method(typeof(Minimap), "SetMapMode", (Type[])null, (Type[])null);
		}
		if (_mapModeEnum == null)
		{
			_mapModeEnum = AccessTools.TypeByName("Minimap+MapMode") ?? typeof(Minimap).GetNestedType("MapMode", BindingFlags.Public | BindingFlags.NonPublic);
		}
		if (_screenToWorld == null)
		{
			_screenToWorld = AccessTools.Method(typeof(Minimap), "ScreenToWorldPoint", new Type[1] { typeof(Vector3) }, (Type[])null);
		}
	}

	internal static void OpenLarge()
	{
		Ensure();
		Minimap instance = Minimap.instance;
		if ((Object)(object)instance == (Object)null || _setMapMode == null || _mapModeEnum == null)
		{
			return;
		}
		try
		{
			object obj = Enum.Parse(_mapModeEnum, "Large", ignoreCase: true);
			_setMapMode.Invoke(instance, new object[1] { obj });
		}
		catch
		{
		}
	}

	internal static void CloseLarge()
	{
		Ensure();
		Minimap instance = Minimap.instance;
		if ((Object)(object)instance == (Object)null || _setMapMode == null || _mapModeEnum == null)
		{
			return;
		}
		try
		{
			object obj = Enum.Parse(_mapModeEnum, "Small", ignoreCase: true);
			_setMapMode.Invoke(instance, new object[1] { obj });
		}
		catch
		{
		}
	}

	internal static bool TryClickWorld(out Vector3 world)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: 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_0066: 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_0076: Unknown result type (might be due to invalid IL or missing references)
		Ensure();
		world = Vector3.zero;
		Minimap instance = Minimap.instance;
		if ((Object)(object)instance == (Object)null || _screenToWorld == null)
		{
			return false;
		}
		try
		{
			if (_screenToWorld.Invoke(instance, new object[1] { Input.mousePosition }) is Vector3 val)
			{
				world = val;
				return true;
			}
		}
		catch
		{
		}
		return false;
	}
}
internal static class WPGfx
{
	internal static class WPFormatting
	{
		public static string Colorize(string text)
		{
			return "<color=#8EE7FF>" + text + "</color>";
		}
	}

	internal static Sprite PortalPinSprite;

	internal static void EnsurePortalSprite()
	{
		if ((Object)(object)PortalPinSprite != (Object)null)
		{
			return;
		}
		ZNetScene instance = ZNetScene.instance;
		if ((Object)(object)instance == (Object)null)
		{
			return;
		}
		foreach (GameObject prefab in instance.m_prefabs)
		{
			if (Object.op_Implicit((Object)(object)prefab) && (Object)(object)prefab.GetComponent<TeleportWorld>() != (Object)null)
			{
				Piece component = prefab.GetComponent<Piece>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.m_icon != (Object)null)
				{
					PortalPinSprite = component.m_icon;
					break;
				}
			}
		}
	}
}
internal static class WPState
{
	private sealed class PortalData
	{
		internal Vector3 Position;

		internal string Name;
	}

	private static readonly Dictionary<ZDOID, PinData> _portalPins = new Dictionary<ZDOID, PinData>();

	private static readonly Dictionary<ZDOID, PortalData> _portalData = new Dictionary<ZDOID, PortalData>();

	private static float _lastMaintenance;

	private const float MaintenanceInterval = 5f;

	internal static bool SelectingDestination;

	internal static bool PendingCloseAfterTeleport;

	internal static bool ReceivedServerSync;

	private static FieldInfo _objectsByIDField;

	private static FieldInfo _minimapPinsField;

	internal static float LastWaypointTeleportTime;

	internal static Vector3 LastWaypointTeleportDest;

	private static IEnumerable<ZDO> EnumerateAllZDOs()
	{
		ZDOMan zdoman = ZDOMan.instance;
		if (zdoman == null)
		{
			yield break;
		}
		if (_objectsByIDField == null)
		{
			_objectsByIDField = AccessTools.Field(typeof(ZDOMan), "m_objectsByID");
		}
		if (!(_objectsByIDField?.GetValue(zdoman) is Dictionary<ZDOID, ZDO> dict))
		{
			yield break;
		}
		foreach (KeyValuePair<ZDOID, ZDO> item in dict)
		{
			ZDO z = item.Value;
			if (z != null)
			{
				yield return z;
			}
		}
	}

	internal static void AddOrUpdatePortalPin(TeleportWorld tp)
	{
		if ((Object)(object)tp == (Object)null || (Object)(object)Minimap.instance == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)tp).GetComponent<ZNetView>();
		if (!((Object)(object)component == (Object)null))
		{
			ZDO zDO = component.GetZDO();
			if (zDO != null)
			{
				AddOrUpdatePortalPinFromZDO(zDO);
			}
		}
	}

	internal static void AddOrUpdatePortalPinFromZDO(ZDO zdo)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: 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)
		if (zdo != null && !((Object)(object)Minimap.instance == (Object)null))
		{
			ZDOID uid = zdo.m_uid;
			Vector3 position = zdo.GetPosition();
			string text = zdo.GetString("tag", "Portal");
			if (string.IsNullOrEmpty(text))
			{
				text = "Portal";
			}
			AddOrUpdatePortalPinFromData(uid, position, text);
		}
	}

	internal static void AddOrUpdatePortalPinFromData(ZDOID id, Vector3 pos, string name)
	{
		//IL_0017: 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)
		//IL_0050: 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_00c4: 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_00f4: 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_006d: 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_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(name))
		{
			name = "Portal";
		}
		_portalData[id] = new PortalData
		{
			Position = pos,
			Name = name
		};
		if ((Object)(object)Minimap.instance == (Object)null)
		{
			return;
		}
		WPGfx.EnsurePortalSprite();
		if (_portalPins.TryGetValue(id, out var value))
		{
			if (IsPinStillRegistered(value))
			{
				value.m_pos = pos;
				value.m_name = WPGfx.WPFormatting.Colorize(name);
				value.m_type = (PinType)3;
				if ((Object)(object)WPGfx.PortalPinSprite != (Object)null)
				{
					value.m_icon = WPGfx.PortalPinSprite;
				}
				return;
			}
			_portalPins.Remove(id);
		}
		PinData val = Minimap.instance.AddPin(pos, (PinType)3, WPGfx.WPFormatting.Colorize(name), false, false, 0L, default(PlatformUserID));
		if (val != null)
		{
			val.m_save = false;
			val.m_doubleSize = false;
			val.m_checked = false;
			val.m_type = (PinType)3;
			if ((Object)(object)WPGfx.PortalPinSprite != (Object)null)
			{
				val.m_icon = WPGfx.PortalPinSprite;
			}
			_portalPins[id] = val;
		}
	}

	private static bool IsPinStillRegistered(PinData pin)
	{
		if (pin == null || (Object)(object)Minimap.instance == (Object)null)
		{
			return false;
		}
		try
		{
			if (_minimapPinsField == null)
			{
				_minimapPinsField = AccessTools.Field(typeof(Minimap), "m_pins");
			}
			return _minimapPinsField?.GetValue(Minimap.instance) is IList<PinData> list && list.Contains(pin);
		}
		catch
		{
			return false;
		}
	}

	internal static void RemovePinsNotIn(HashSet<ZDOID> validIds)
	{
		//IL_003e: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Minimap.instance == (Object)null || validIds == null)
		{
			return;
		}
		List<ZDOID> list = new List<ZDOID>();
		foreach (KeyValuePair<ZDOID, PinData> portalPin in _portalPins)
		{
			if (!validIds.Contains(portalPin.Key))
			{
				if (portalPin.Value != null && IsPinStillRegistered(portalPin.Value))
				{
					Minimap.instance.RemovePin(portalPin.Value);
				}
				list.Add(portalPin.Key);
			}
		}
		foreach (ZDOID item in list)
		{
			_portalPins.Remove(item);
			_portalData.Remove(item);
		}
	}

	internal static void ResetForNewSession()
	{
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Minimap.instance != (Object)null)
		{
			foreach (PinData value in _portalPins.Values)
			{
				if (value != null && IsPinStillRegistered(value))
				{
					Minimap.instance.RemovePin(value);
				}
			}
		}
		_portalPins.Clear();
		_portalData.Clear();
		ReceivedServerSync = false;
		SelectingDestination = false;
		PendingCloseAfterTeleport = false;
		LastWaypointTeleportTime = 0f;
		LastWaypointTeleportDest = Vector3.zero;
		_lastMaintenance = 0f;
	}

	internal static void ResetPinsForNewMinimap()
	{
		_portalPins.Clear();
		_minimapPinsField = null;
		_lastMaintenance = 0f;
	}

	internal static void RemovePortalPin(ZDOID id)
	{
		//IL_0017: 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_004b: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)Minimap.instance == (Object)null))
		{
			if (_portalPins.TryGetValue(id, out var value) && value != null)
			{
				Minimap.instance.RemovePin(value);
			}
			_portalPins.Remove(id);
			_portalData.Remove(id);
		}
	}

	private static bool IsPortalZDO(ZDO zdo)
	{
		if (zdo == null || (Object)(object)ZNetScene.instance == (Object)null)
		{
			return false;
		}
		try
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab());
			return (Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<TeleportWorld>() != (Object)null;
		}
		catch
		{
			return false;
		}
	}

	internal static void RebuildPinsFromZDOs()
	{
		if ((Object)(object)Minimap.instance == (Object)null)
		{
			return;
		}
		foreach (ZDO item in EnumerateAllZDOs())
		{
			try
			{
				if (IsPortalZDO(item))
				{
					AddOrUpdatePortalPinFromZDO(item);
				}
			}
			catch
			{
			}
		}
	}

	internal static void RemoveMissingPins()
	{
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Minimap.instance == (Object)null || ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer() && ReceivedServerSync))
		{
			return;
		}
		ZDOMan instance = ZDOMan.instance;
		if (instance == null)
		{
			return;
		}
		List<ZDOID> list = new List<ZDOID>();
		foreach (KeyValuePair<ZDOID, PinData> portalPin in _portalPins)
		{
			ZDOID key = portalPin.Key;
			PinData value = portalPin.Value;
			ZDO zDO = instance.GetZDO(key);
			if (zDO == null)
			{
				if (value != null)
				{
					Minimap.instance.RemovePin(value);
				}
				list.Add(key);
				if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
				{
					WaypointPortalsServer.NotifyPortalDestroyedById(key);
				}
			}
		}
		for (int i = 0; i < list.Count; i++)
		{
			_portalPins.Remove(list[i]);
		}
	}

	internal static void Maintenance()
	{
		//IL_0054: 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 (Time.unscaledTime - _lastMaintenance < 5f)
		{
			return;
		}
		_lastMaintenance = Time.unscaledTime;
		if ((Object)(object)Minimap.instance == (Object)null)
		{
			return;
		}
		List<KeyValuePair<ZDOID, PortalData>> list = new List<KeyValuePair<ZDOID, PortalData>>(_portalData);
		foreach (KeyValuePair<ZDOID, PortalData> item in list)
		{
			AddOrUpdatePortalPinFromData(item.Key, item.Value.Position, item.Value.Name);
		}
	}

	internal static bool IsLocal(Player p)
	{
		return (Object)(object)p != (Object)null && (Object)(object)p == (Object)(object)Player.m_localPlayer;
	}

	internal static PinData FindNearestPortalPin(Vector3 world, float maxRange)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		PinData result = null;
		float num = maxRange * maxRange;
		foreach (KeyValuePair<ZDOID, PinData> portalPin in _portalPins)
		{
			PinData value = portalPin.Value;
			if (value != null)
			{
				Vector3 val = value.m_pos - world;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (sqrMagnitude <= num)
				{
					num = sqrMagnitude;
					result = value;
				}
			}
		}
		return result;
	}

	internal static TeleportWorld FindNearestPortal(Vector3 worldPos, float maxRange)
	{
		//IL_001b: 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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		TeleportWorld result = null;
		float num = maxRange * maxRange;
		TeleportWorld[] array = Object.FindObjectsByType<TeleportWorld>((FindObjectsSortMode)0);
		for (int i = 0; i < array.Length; i++)
		{
			Vector3 position = ((Component)array[i]).transform.position;
			Vector3 val = position - worldPos;
			float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
			if (sqrMagnitude <= num)
			{
				num = sqrMagnitude;
				result = array[i];
			}
		}
		return result;
	}
}
internal static class WaypointPortalsServer
{
	private static ZRoutedRpc _registeredRpc;

	private static FieldInfo _objectsByIDField;

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

	private static readonly HashSet<int> _portalPrefabHashes = new HashSet<int>();

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

	private static bool _portalPrefabHashesBuilt;

	private static float _lastMaintenance;

	private const float MaintenanceInterval = 5f;

	public static void InitServer()
	{
		if (ZRoutedRpc.instance != null && _registeredRpc != ZRoutedRpc.instance)
		{
			_registeredRpc = ZRoutedRpc.instance;
			ZRoutedRpc.instance.Register<ZPackage>("WP_RequestPortalSync", (Action<long, ZPackage>)RPC_RequestPortalSync);
			ZRoutedRpc.instance.Register<ZPackage>("WP_PortalUpsert", (Action<long, ZPackage>)delegate
			{
			});
			ZRoutedRpc.instance.Register<ZPackage>("WP_PortalDestroyed", (Action<long, ZPackage>)delegate
			{
			});
			WaypointPortalsPlugin.Log.LogInfo((object)"[WaypointPortals] Server RPCs registered");
		}
	}

	private static IEnumerable<ZDO> EnumerateAllZDOs()
	{
		ZDOMan zdoman = ZDOMan.instance;
		if (zdoman == null)
		{
			yield break;
		}
		if (_objectsByIDField == null)
		{
			_objectsByIDField = AccessTools.Field(typeof(ZDOMan), "m_objectsByID");
		}
		if (!(_objectsByIDField?.GetValue(zdoman) is Dictionary<ZDOID, ZDO> dict))
		{
			yield break;
		}
		foreach (KeyValuePair<ZDOID, ZDO> kv in dict)
		{
			if (kv.Value != null)
			{
				yield return kv.Value;
			}
		}
	}

	private static void EnsurePortalPrefabHashes()
	{
		if (_portalPrefabHashesBuilt || (Object)(object)ZNetScene.instance == (Object)null)
		{
			return;
		}
		_portalPrefabHashes.Clear();
		foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
		{
			if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<TeleportWorld>() != (Object)null)
			{
				_portalPrefabHashes.Add(StringExtensionMethods.GetStableHashCode(((Object)prefab).name));
			}
		}
		_portalPrefabHashesBuilt = true;
		WaypointPortalsPlugin.Log.LogInfo((object)$"[WaypointPortals] Found {_portalPrefabHashes.Count} portal prefab type(s)");
	}

	private static bool IsPortalZDO(ZDO zdo)
	{
		if (zdo == null)
		{
			return false;
		}
		EnsurePortalPrefabHashes();
		return _portalPrefabHashes.Contains(zdo.GetPrefab());
	}

	internal static void SyncPortalsToLocalPlayer()
	{
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)Minimap.instance == (Object)null || ZDOMan.instance == null)
		{
			return;
		}
		HashSet<ZDOID> hashSet = new HashSet<ZDOID>();
		int num = 0;
		foreach (ZDO item in EnumerateAllZDOs())
		{
			try
			{
				if (IsPortalZDO(item))
				{
					_knownPortalIds.Add(item.m_uid);
					hashSet.Add(item.m_uid);
					WPState.AddOrUpdatePortalPinFromData(item.m_uid, item.GetPosition(), item.GetString("tag", ""));
					num++;
				}
			}
			catch
			{
			}
		}
		WPState.RemovePinsNotIn(hashSet);
		WPState.ReceivedServerSync = true;
		WaypointPortalsPlugin.Log.LogInfo((object)$"[WaypointPortals] Loaded {num} portals directly for local host");
	}

	private static void SendAllPortalsToPeer(long peerID)
	{
		//IL_0086: 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_00b1: Expected O, but got Unknown
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		ZDOMan instance = ZDOMan.instance;
		if (instance == null)
		{
			return;
		}
		List<ZDO> list = new List<ZDO>();
		foreach (ZDO item in EnumerateAllZDOs())
		{
			try
			{
				if (IsPortalZDO(item))
				{
					list.Add(item);
				}
			}
			catch
			{
			}
		}
		foreach (ZDO item2 in list)
		{
			_knownPortalIds.Add(item2.m_uid);
		}
		ZPackage val = new ZPackage();
		val.Write(list.Count);
		foreach (ZDO item3 in list)
		{
			val.Write(item3.m_uid);
			val.Write(item3.GetPosition());
			val.Write(item3.GetString("tag", ""));
		}
		WaypointPortalsPlugin.Log.LogInfo((object)$"[WaypointPortals] Sending {list.Count} portals to peer {peerID}");
		ZRoutedRpc.instance.InvokeRoutedRPC(peerID, "WP_SyncPortals", new object[1] { val });
	}

	private static void RPC_RequestPortalSync(long sender, ZPackage pkg)
	{
		WaypointPortalsPlugin.Log.LogInfo((object)$"[WaypointPortals] Received portal sync request from {sender}");
		SendAllPortalsToPeer(sender);
	}

	internal static void QueueCreatedZDO(ZDO zdo, int prefabHash)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		if (zdo != null && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
		{
			EnsurePortalPrefabHashes();
			if (_portalPrefabHashes.Contains(prefabHash) && !_knownPortalIds.Contains(zdo.m_uid))
			{
				_pendingCreatedPortalIds.Add(zdo.m_uid);
			}
		}
	}

	private static void NotifyPortalChanged(ZDO zdo)
	{
		//IL_0049: 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_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		//IL_006d: 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)
		if (zdo != null && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && ZRoutedRpc.instance != null && IsPortalZDO(zdo))
		{
			_pendingCreatedPortalIds.Remove(zdo.m_uid);
			_knownPortalIds.Add(zdo.m_uid);
			ZPackage val = new ZPackage();
			val.Write(zdo.m_uid);
			val.Write(zdo.GetPosition());
			val.Write(zdo.GetString("tag", ""));
			ZRoutedRpc.instance.InvokeRoutedRPC(0L, "WP_PortalUpsert", new object[1] { val });
		}
	}

	internal static void NotifyPortalChanged(TeleportWorld tp)
	{
		if (!((Object)(object)tp == (Object)null))
		{
			ZNetView component = ((Component)tp).GetComponent<ZNetView>();
			NotifyPortalChanged(((Object)(object)component != (Object)null) ? component.GetZDO() : null);
		}
	}

	private static void FlushCreatedPortalQueue()
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		if (_pendingCreatedPortalIds.Count == 0 || ZDOMan.instance == null)
		{
			return;
		}
		ZDOID[] array = (ZDOID[])(object)new ZDOID[_pendingCreatedPortalIds.Count];
		_pendingCreatedPortalIds.CopyTo(array);
		ZDOID[] array2 = array;
		foreach (ZDOID val in array2)
		{
			ZDO zDO = ZDOMan.instance.GetZDO(val);
			if (zDO == null)
			{
				_pendingCreatedPortalIds.Remove(val);
			}
			else
			{
				NotifyPortalChanged(zDO);
			}
		}
	}

	internal static void Maintenance()
	{
		//IL_0061: 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_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		FlushCreatedPortalQueue();
		if (Time.unscaledTime - _lastMaintenance < 5f)
		{
			return;
		}
		_lastMaintenance = Time.unscaledTime;
		ZDOMan instance = ZDOMan.instance;
		if (instance == null || _knownPortalIds.Count == 0)
		{
			return;
		}
		List<ZDOID> list = null;
		foreach (ZDOID knownPortalId in _knownPortalIds)
		{
			if (instance.GetZDO(knownPortalId) == null)
			{
				if (list == null)
				{
					list = new List<ZDOID>();
				}
				list.Add(knownPortalId);
			}
		}
		if (list == null)
		{
			return;
		}
		foreach (ZDOID item in list)
		{
			_knownPortalIds.Remove(item);
			NotifyPortalDestroyedById(item);
		}
	}

	internal static void NotifyPortalDestroyedById(ZDOID id)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected O, but got Unknown
		//IL_0039: 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)
		if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && ZRoutedRpc.instance != null)
		{
			ZPackage val = new ZPackage();
			val.Write(id);
			WaypointPortalsPlugin.Log.LogInfo((object)$"[WaypointPortals] Broadcasting portal destroy for {id}");
			ZRoutedRpc.instance.InvokeRoutedRPC(0L, "WP_PortalDestroyed", new object[1] { val });
		}
	}
}
internal static class WaypointPortalsClient
{
	private static ZRoutedRpc _registeredRpc;

	private static bool _syncPending;

	private static float _lastSyncRequest = -9999f;

	private const float SyncRetryInterval = 5f;

	public static void InitClient()
	{
		if (ZRoutedRpc.instance != null && _registeredRpc != ZRoutedRpc.instance)
		{
			_registeredRpc = ZRoutedRpc.instance;
			_syncPending = false;
			_lastSyncRequest = -9999f;
			ZRoutedRpc.instance.Register<ZPackage>("WP_SyncPortals", (Action<long, ZPackage>)RPC_SyncPortals);
			ZRoutedRpc.instance.Register<ZPackage>("WP_PortalUpsert", (Action<long, ZPackage>)RPC_PortalUpsert);
			ZRoutedRpc.instance.Register<ZPackage>("WP_PortalDestroyed", (Action<long, ZPackage>)RPC_PortalDestroyed);
			WaypointPortalsPlugin.Log.LogInfo((object)"[WaypointPortals] Client RPCs registered");
		}
	}

	public static void RequestSync(bool force = false)
	{
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Expected O, but got Unknown
		if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null || ZNet.instance.IsServer())
		{
			return;
		}
		float unscaledTime = Time.unscaledTime;
		if (force || !_syncPending || !(unscaledTime - _lastSyncRequest < 5f))
		{
			ZNetPeer serverPeer = ZNet.instance.GetServerPeer();
			if (serverPeer != null)
			{
				_syncPending = true;
				_lastSyncRequest = unscaledTime;
				long uid = serverPeer.m_uid;
				ZPackage val = new ZPackage();
				WaypointPortalsPlugin.Log.LogInfo((object)$"[WaypointPortals] Requesting portal sync from server {uid}");
				ZRoutedRpc.instance.InvokeRoutedRPC(uid, "WP_RequestPortalSync", new object[1] { val });
			}
		}
	}

	internal static void Maintenance()
	{
		if (!((Object)(object)ZNet.instance == (Object)null) && ZRoutedRpc.instance != null && !ZNet.instance.IsServer())
		{
			InitClient();
			float unscaledTime = Time.unscaledTime;
			if (!WPState.ReceivedServerSync && (!_syncPending || unscaledTime - _lastSyncRequest >= 5f))
			{
				RequestSync(force: true);
			}
		}
	}

	private static void RPC_SyncPortals(long sender, ZPackage pkg)
	{
		//IL_0063: 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_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)
		//IL_007b: 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_0085: Unknown result type (might be due to invalid IL or missing references)
		_syncPending = false;
		int num = pkg.ReadInt();
		WaypointPortalsPlugin.Log.LogInfo((object)$"[WaypointPortals] Received portal sync: {num} entries from {sender}");
		if ((Object)(object)Minimap.instance == (Object)null)
		{
			WPState.ReceivedServerSync = false;
			WaypointPortalsPlugin.Log.LogWarning((object)"[WaypointPortals] Minimap not ready; portal sync will be retried");
			return;
		}
		HashSet<ZDOID> hashSet = new HashSet<ZDOID>();
		for (int i = 0; i < num; i++)
		{
			ZDOID val = pkg.ReadZDOID();
			Vector3 pos = pkg.ReadVector3();
			string name = pkg.ReadString();
			hashSet.Add(val);
			WPState.AddOrUpdatePortalPinFromData(val, pos, name);
		}
		WPState.RemovePinsNotIn(hashSet);
		WPState.ReceivedServerSync = true;
	}

	private static void RPC_PortalUpsert(long sender, ZPackage pkg)
	{
		//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_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: 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_0017: Unknown result type (might be due to invalid IL or missing references)
		ZDOID id = pkg.ReadZDOID();
		Vector3 pos = pkg.ReadVector3();
		string name = pkg.ReadString();
		WPState.AddOrUpdatePortalPinFromData(id, pos, name);
	}

	private static void RPC_PortalDestroyed(long sender, ZPackage pkg)
	{
		//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_0012: 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)
		ZDOID val = pkg.ReadZDOID();
		WaypointPortalsPlugin.Log.LogInfo((object)$"[WaypointPortals] Portal destroyed, removing pin {val}");
		WPState.RemovePortalPin(val);
	}
}
[HarmonyPatch(typeof(ZNet), "Awake")]
public static class ZNet_Awake_WaypointPortalsNetInit
{
	private static void Postfix(ZNet __instance)
	{
		if (ZRoutedRpc.instance != null)
		{
			WPState.ResetForNewSession();
			if (__instance.IsServer())
			{
				WaypointPortalsServer.InitServer();
			}
			else
			{
				WaypointPortalsClient.InitClient();
			}
		}
	}
}
[HarmonyPatch(typeof(TeleportWorld), "Teleport")]
public static class TeleportWorld_Teleport_Intercept
{
	private static bool Prefix(TeleportWorld __instance, Player player)
	{
		if (!WPState.IsLocal(player))
		{
			return true;
		}
		WPState.SelectingDestination = true;
		WPState.PendingCloseAfterTeleport = false;
		MapApi.OpenLarge();
		return false;
	}
}
[HarmonyPatch]
public static class ZDOMan_CreateNewZDO_PortalHook
{
	private static MethodBase TargetMethod()
	{
		return AccessTools.Method(typeof(ZDOMan), "CreateNewZDO", new Type[3]
		{
			typeof(ZDOID),
			typeof(Vector3),
			typeof(int)
		}, (Type[])null);
	}

	private static void Postfix(ZDO __result, object[] __args)
	{
		if (__result != null && __args != null && __args.Length >= 3 && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
		{
			int prefabHash = (int)__args[2];
			WaypointPortalsServer.QueueCreatedZDO(__result, prefabHash);
		}
	}
}
[HarmonyPatch(typeof(TeleportWorld), "Awake")]
public static class TeleportWorld_Awake_Pin
{
	private static void Postfix(TeleportWorld __instance)
	{
		WPState.AddOrUpdatePortalPin(__instance);
		if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
		{
			WaypointPortalsServer.NotifyPortalChanged(__instance);
		}
	}
}
[HarmonyPatch(typeof(TeleportWorld), "UpdatePortal")]
public static class TeleportWorld_UpdatePortal_Pin
{
	private static void Postfix(TeleportWorld __instance)
	{
		WPState.AddOrUpdatePortalPin(__instance);
	}
}
[HarmonyPatch(typeof(TeleportWorld), "HaveTarget")]
public static class TeleportWorld_HaveTarget_AlwaysTrue
{
	private static void Postfix(ref bool __result)
	{
		__result = true;
	}
}
[HarmonyPatch(typeof(TeleportWorld), "TargetFound")]
public static class TeleportWorld_TargetFound_AlwaysTrue
{
	private static void Postfix(ref bool __result)
	{
		__result = true;
	}
}
[HarmonyPatch(typeof(TeleportWorld), "RPC_SetTag")]
public static class TeleportWorld_RPC_SetTag_UpdatePin
{
	private static void Postfix(TeleportWorld __instance)
	{
		WPState.AddOrUpdatePortalPin(__instance);
		if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
		{
			WaypointPortalsServer.NotifyPortalChanged(__instance);
		}
	}
}
[HarmonyPatch(typeof(Minimap), "Awake")]
public static class Minimap_Awake_Rebuild
{
	private static void Postfix()
	{
		WPState.ResetPinsForNewMinimap();
		WPState.Maintenance();
		if ((Object)(object)ZNet.instance != (Object)null)
		{
			if (ZNet.instance.IsServer())
			{
				WaypointPortalsServer.SyncPortalsToLocalPlayer();
			}
			else if (!WPState.ReceivedServerSync)
			{
				WaypointPortalsClient.RequestSync();
			}
		}
	}
}
[HarmonyPatch(typeof(Minimap), "SetMapMode")]
public static class Minimap_SetMapMode_WaypointClear
{
	private static void Postfix(MapMode mode)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Invalid comparison between Unknown and I4
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: 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_005d: 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)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		Minimap instance = Minimap.instance;
		if ((int)mode == 2)
		{
			float num = Time.unscaledTime - WPState.LastWaypointTeleportTime;
			if (!(num >= 0f) || !(num < 5f))
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				Vector3 position = ((Component)localPlayer).transform.position;
				Vector3 val = position - WPState.LastWaypointTeleportDest;
				if (((Vector3)(ref val)).sqrMagnitude < 25f)
				{
					WPState.SelectingDestination = false;
					WPState.PendingCloseAfterTeleport = false;
					MapApi.CloseLarge();
				}
			}
		}
		else
		{
			WPState.SelectingDestination = false;
			WPState.PendingCloseAfterTeleport = false;
		}
	}
}
[HarmonyPatch(typeof(Player), "OnSpawned")]
public static class Player_OnSpawned_Rebuild_And_RequestSync
{
	private static void Postfix(Player __instance)
	{
		WPState.Maintenance();
		if ((Object)(object)ZNet.instance != (Object)null)
		{
			if (ZNet.instance.IsServer())
			{
				WaypointPortalsServer.SyncPortalsToLocalPlayer();
			}
			else
			{
				WaypointPortalsClient.RequestSync();
			}
		}
	}
}
[HarmonyPatch(typeof(Minimap), "OnMapLeftClick")]
public static class Minimap_OnMapLeftClick_WaypointTeleport
{
	private static bool Prefix()
	{
		//IL_00a8: 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_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: 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_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		if (!WPState.SelectingDestination)
		{
			return true;
		}
		if (!MapApi.TryClickWorld(out var world))
		{
			return true;
		}
		PinData val = WPState.FindNearestPortalPin(world, 300f);
		if (val == null)
		{
			return true;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return true;
		}
		try
		{
			if (!((Humanoid)localPlayer).IsTeleportable(false))
			{
				((Character)localPlayer).Message((MessageType)2, "$msg_noteleport_carry", 0, (Sprite)null, false);
				WPState.SelectingDestination = false;
				WPState.PendingCloseAfterTeleport = false;
				return false;
			}
		}
		catch
		{
		}
		TeleportWorld val2 = WPState.FindNearestPortal(val.m_pos, 10f);
		Vector3 val3;
		Quaternion val4;
		if ((Object)(object)val2 != (Object)null)
		{
			Vector3 forward = ((Component)val2).transform.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
			{
				forward = Vector3.forward;
			}
			((Vector3)(ref forward)).Normalize();
			float num = 4f;
			val3 = ((Component)val2).transform.position + forward * num;
			val3.y = ((Component)val2).transform.position.y + 0.5f;
			val4 = Quaternion.LookRotation(forward);
		}
		else
		{
			val3 = val.m_pos + Vector3.up * 0.5f;
			val4 = Quaternion.identity;
		}
		WPState.LastWaypointTeleportTime = Time.unscaledTime;
		WPState.LastWaypointTeleportDest = val3;
		WPState.PendingCloseAfterTeleport = true;
		((Character)localPlayer).TeleportTo(val3, val4, true);
		return false;
	}
}
[HarmonyPatch(typeof(Player), "TeleportTo")]
public static class Player_TeleportTo_WaypointCloseMap
{
	private static void Postfix(Player __instance)
	{
		if (WPState.IsLocal(__instance) && WPState.PendingCloseAfterTeleport)
		{
			WPState.PendingCloseAfterTeleport = false;
			WPState.SelectingDestination = false;
			MapApi.CloseLarge();
		}
	}
}