Decompiled source of OttoBifrost v1.3.2

OttoBifrost.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using OttoBifrost.Components;
using OttoBifrost.Patches;
using ServerSync;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("OttoBifrost")]
[assembly: AssemblyCompany("potto007")]
[assembly: AssemblyProduct("OttoBifrost")]
[assembly: AssemblyCopyright("Copyright (c) 2026 Paul Otto")]
[assembly: ComVisible(false)]
[assembly: Guid("EDE07575-F656-4406-985E-38F1390B528E")]
[assembly: AssemblyFileVersion("1.3.2")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.2.0")]
[module: UnverifiableCode]
[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 OttoBifrost
{
	internal readonly struct Destination
	{
		public readonly Vector3 Position;

		public readonly Vector3 Forward;

		public readonly Vector2s Zone;

		public readonly int Radius;

		public Destination(Vector3 position, Vector3 forward, int radius)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			Position = position;
			Forward = forward;
			Zone = ZoneSystem.GetZone(position);
			Radius = radius;
		}
	}
	internal static class Destinations
	{
		private sealed class PortalRequest
		{
			public Vector3 Position;

			public Vector3 Forward;

			public int Radius;

			public float Distance;
		}

		private const int ArrivalRadius = 3;

		private const int SecondaryRadius = 1;

		private const float NearestSwitchMargin = 2f;

		private static readonly Dictionary<ZDOID, PortalRequest> Requests = new Dictionary<ZDOID, PortalRequest>();

		private static readonly List<PortalRequest> Others = new List<PortalRequest>();

		private static readonly List<Destination> Pending = new List<Destination>();

		private static readonly Comparison<PortalRequest> ByDistance = (PortalRequest a, PortalRequest b) => a.Distance.CompareTo(b.Distance);

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

		private static ZDOID _nearest = ZDOID.None;

		private static bool _teleporting;

		private static bool _holdingArrival;

		private static Vector3 _arrival;

		private static float _arrivalReleaseTime = float.MaxValue;

		internal static Destination[] Active = Array.Empty<Destination>();

		internal static bool Any => Active.Length != 0;

		internal static void Request(ZDOID portal, Vector3 farEnd, Vector3 farForward, int radius, float distance)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!Requests.TryGetValue(portal, out PortalRequest value))
			{
				value = new PortalRequest();
				Requests.Add(portal, value);
			}
			DeferredReleases.Remove(portal);
			value.Position = farEnd;
			value.Forward = farForward;
			value.Radius = radius;
			value.Distance = distance;
			Rebuild();
		}

		internal static void Release(ZDOID portal)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (_teleporting)
			{
				if (Requests.ContainsKey(portal))
				{
					DeferredReleases.Add(portal);
				}
			}
			else if (Requests.Remove(portal))
			{
				Rebuild();
			}
		}

		internal static void BeginTeleport()
		{
			_teleporting = true;
		}

		internal static void EndTeleport(Vector3 landing, float holdSeconds)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			_teleporting = false;
			foreach (ZDOID deferredRelease in DeferredReleases)
			{
				Requests.Remove(deferredRelease);
			}
			DeferredReleases.Clear();
			_holdingArrival = true;
			_arrival = landing;
			_arrivalReleaseTime = Time.time + holdSeconds;
			Rebuild();
		}

		internal static void Tick()
		{
			if (_holdingArrival && Time.time >= _arrivalReleaseTime)
			{
				_holdingArrival = false;
				_arrivalReleaseTime = float.MaxValue;
				Rebuild();
			}
		}

		internal static bool Covers(Vector2s zone)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			Destination[] active = Active;
			for (int i = 0; i < active.Length; i++)
			{
				Destination destination = active[i];
				if (Mathf.Abs(zone.x - destination.Zone.x) <= destination.Radius && Mathf.Abs(zone.y - destination.Zone.y) <= destination.Radius)
				{
					return true;
				}
			}
			return false;
		}

		internal static bool IsNear(Vector3 position, float tolerance)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			float num = tolerance * tolerance;
			Destination[] active = Active;
			for (int i = 0; i < active.Length; i++)
			{
				Vector3 val = active[i].Position - position;
				if (((Vector3)(ref val)).sqrMagnitude < num)
				{
					return true;
				}
			}
			return false;
		}

		internal static void Clear()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Requests.Clear();
			DeferredReleases.Clear();
			_teleporting = false;
			_nearest = ZDOID.None;
			_holdingArrival = false;
			_arrivalReleaseTime = float.MaxValue;
			Active = Array.Empty<Destination>();
		}

		private static void Rebuild()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_00f7: 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_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			ZDOID val = PickNearest();
			if (PerfStats.Enabled && _nearest != ZDOID.None && val != ZDOID.None && val != _nearest)
			{
				PerfStats.NearestSwitches++;
			}
			_nearest = val;
			Pending.Clear();
			Others.Clear();
			foreach (KeyValuePair<ZDOID, PortalRequest> request in Requests)
			{
				if (request.Key == val)
				{
					Pending.Add(new Destination(request.Value.Position, request.Value.Forward, request.Value.Radius));
				}
				else
				{
					Others.Add(request.Value);
				}
			}
			if (_holdingArrival)
			{
				Pending.Add(new Destination(_arrival, Vector3.zero, (val != ZDOID.None) ? 1 : 3));
			}
			Others.Sort(ByDistance);
			foreach (PortalRequest other in Others)
			{
				Pending.Add(new Destination(other.Position, other.Forward, Mathf.Min(other.Radius, 1)));
			}
			if (!MatchesActive(Pending))
			{
				Active = Pending.ToArray();
			}
		}

		private static ZDOID PickNearest()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			ZDOID val = ZDOID.None;
			float num = float.MaxValue;
			foreach (KeyValuePair<ZDOID, PortalRequest> request in Requests)
			{
				if (request.Value.Distance < num)
				{
					val = request.Key;
					num = request.Value.Distance;
				}
			}
			if (val != _nearest && Requests.TryGetValue(_nearest, out PortalRequest value) && num > value.Distance - 2f)
			{
				return _nearest;
			}
			return val;
		}

		private static bool MatchesActive(List<Destination> candidate)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (candidate.Count != Active.Length)
			{
				return false;
			}
			for (int i = 0; i < Active.Length; i++)
			{
				if (Active[i].Position != candidate[i].Position || Active[i].Radius != candidate[i].Radius)
				{
					return false;
				}
			}
			return true;
		}
	}
	[BepInPlugin("potto007.OttoBifrost", "OttoBifrost", "1.3.2")]
	public class OttoBifrostPlugin : BaseUnityPlugin
	{
		internal enum PreviewModes
		{
			StaticView,
			LiveView
		}

		internal const string ModName = "OttoBifrost";

		internal const string ModVersion = "1.3.2";

		internal const string Author = "potto007";

		internal const string ModGUID = "potto007.OttoBifrost";

		internal static readonly ManualLogSource Log = Logger.CreateLogSource("OttoBifrost");

		private readonly Harmony _harmony = new Harmony("potto007.OttoBifrost");

		private static readonly ConfigSync ConfigSync = new ConfigSync("potto007.OttoBifrost")
		{
			DisplayName = "OttoBifrost",
			CurrentVersion = "1.3.2",
			MinimumRequiredVersion = "1.3.2"
		};

		private const string GeneralSection = "OttoBifrost";

		private const string PreviewSection = "Preview";

		private const string DebugSection = "Debug";

		private const string ConfigFileName = "potto007.OttoBifrost.cfg";

		private static readonly Version StaticViewDefaultSince = new Version(1, 2, 0);

		private static readonly Regex SavedByHeader = new Regex("^## Settings file was created by plugin .+ v(\\d+(?:\\.\\d+){1,3})");

		internal static ConfigEntry<bool> LockConfiguration = null;

		internal static ConfigEntry<bool> PreloadDestinations = null;

		internal static ConfigEntry<bool> FastTeleport = null;

		internal static ConfigEntry<PreviewModes> PreviewMode = null;

		internal static ConfigEntry<bool> LogPerformance = null;

		private FileSystemWatcher? _configWatcher;

		private void Awake()
		{
			BindConfig();
			_harmony.PatchAll(typeof(OttoBifrostPlugin).Assembly);
			WatchConfigFile();
			Log.LogInfo((object)"OttoBifrost 1.3.2 loaded.");
		}

		private void Update()
		{
			PerfStats.Tick(Time.unscaledDeltaTime, LogPerformance.Value);
			Destinations.Tick();
			DestinationSync.ClientUpdate();
		}

		private void OnDestroy()
		{
			_configWatcher?.Dispose();
			_harmony.UnpatchSelf();
		}

		private void BindConfig()
		{
			Version? savedBy = ReadSavedByVersion();
			LockConfiguration = BindSynced("OttoBifrost", "LockConfiguration", value: true, "If on, only server admins can change the synced settings.");
			ConfigSync.AddLockingConfigEntry<bool>(LockConfiguration);
			PreloadDestinations = BindSynced("OttoBifrost", "PreloadDestinations", value: true, "Load the area around a portal's destination while you stand near the portal.");
			FastTeleport = BindSynced("OttoBifrost", "FastTeleport", value: true, "Skip the vanilla wait when the destination is already loaded.");
			PreviewMode = ((BaseUnityPlugin)this).Config.Bind<PreviewModes>("Preview", "PreviewMode", PreviewModes.StaticView, "StaticView shows one picture of the destination, taken once its objects are built, and renders nothing after that. LiveView renders the nearest portal's destination continuously and follows your head. Not synced.");
			LogPerformance = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogPerformance", false, "Write a timing summary to the log every 5 seconds. Leave off in normal play. Not synced.");
			MigratePreviewMode(savedBy);
		}

		private Version? ReadSavedByVersion()
		{
			try
			{
				if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath))
				{
					return null;
				}
				using StreamReader streamReader = new StreamReader(((BaseUnityPlugin)this).Config.ConfigFilePath);
				Match match = SavedByHeader.Match(streamReader.ReadLine() ?? string.Empty);
				return match.Success ? new Version(match.Groups[1].Value) : null;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not read the version header of potto007.OttoBifrost.cfg: " + ex.Message));
				return null;
			}
		}

		private static void MigratePreviewMode(Version? savedBy)
		{
			if (!(savedBy == null) && !(savedBy >= StaticViewDefaultSince) && PreviewMode.Value == PreviewModes.LiveView)
			{
				PreviewMode.Value = PreviewModes.StaticView;
				Log.LogInfo((object)string.Format("PreviewMode changed from LiveView to StaticView, the default since v{0}. {1} was last saved by v{2}.", StaticViewDefaultSince.ToString(3), "potto007.OttoBifrost.cfg", savedBy));
			}
		}

		private ConfigEntry<T> BindSynced<T>(string section, string key, T value, string description)
		{
			ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, value, description + " [Synced with Server]");
			ConfigSync.AddConfigEntry<T>(val).SynchronizedConfig = true;
			return val;
		}

		private void WatchConfigFile()
		{
			_configWatcher = new FileSystemWatcher(Paths.ConfigPath, "potto007.OttoBifrost.cfg")
			{
				SynchronizingObject = ThreadingHelper.SynchronizingObject
			};
			_configWatcher.Changed += OnConfigFileChanged;
			_configWatcher.Created += OnConfigFileChanged;
			_configWatcher.Renamed += OnConfigFileChanged;
			_configWatcher.EnableRaisingEvents = true;
		}

		private void OnConfigFileChanged(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(Path.Combine(Paths.ConfigPath, "potto007.OttoBifrost.cfg")))
			{
				return;
			}
			try
			{
				((BaseUnityPlugin)this).Config.Reload();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Could not reload potto007.OttoBifrost.cfg. Check the entries for spelling and format: " + ex.Message));
			}
		}
	}
	internal static class Portals
	{
		private static readonly int WoodPortal = StringExtensionMethods.GetStableHashCode("portal_wood");

		private static readonly int StonePortal = StringExtensionMethods.GetStableHashCode("portal_stone");

		internal static bool IsPortal(ZDO zdo)
		{
			int prefab = zdo.GetPrefab();
			if (prefab != WoodPortal)
			{
				return prefab == StonePortal;
			}
			return true;
		}

		internal static bool IsStonePortal(ZDO zdo)
		{
			return zdo.GetPrefab() == StonePortal;
		}

		internal static ZDO? ZdoOf(TeleportWorld portal)
		{
			if (!((Object)(object)portal.m_nview != (Object)null) || !portal.m_nview.IsValid())
			{
				return null;
			}
			return portal.m_nview.GetZDO();
		}

		internal static ZDO? FarEnd(ZDO portal)
		{
			//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_0008: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			ZDOID connectionZDOID = portal.GetConnectionZDOID((ConnectionType)1);
			if (!(connectionZDOID == ZDOID.None) && ZDOMan.instance != null)
			{
				return ZDOMan.instance.GetZDO(connectionZDOID);
			}
			return null;
		}
	}
}
namespace OttoBifrost.Patches
{
	[HarmonyPatch]
	internal static class DestinationSync
	{
		private sealed class PeerDestination(ZDOID remoteId, Vector2s remoteZone, Vector3 sourcePortalPos)
		{
			public readonly ZDOID RemoteId = remoteId;

			public readonly Vector2s RemoteZone = remoteZone;

			public readonly Vector3 SourcePortalPos = sourcePortalPos;

			public bool? ReportedComplete;
		}

		internal const string SetDestinationsRpc = "OttoBifrostSetDestinations";

		internal const string DestinationStateRpc = "OttoBifrostDestinationState";

		private const int MaxDestinationsPerPeer = 8;

		private const int ServerZoneRadius = 1;

		private const float MaxSourcePortalDistance = 30f;

		private const float MinSendInterval = 0.25f;

		private const int IncompleteThreshold = 16;

		private const float ExitPointTolerance = 5f;

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

		private static readonly Dictionary<ZDOID, bool> DestinationComplete = new Dictionary<ZDOID, bool>();

		private static readonly Dictionary<ZDOID, bool> LoggedStates = new Dictionary<ZDOID, bool>();

		private static bool _dirty;

		private static float _lastSendTime = float.MinValue;

		private static readonly Dictionary<long, List<PeerDestination>> PeerDestinations = new Dictionary<long, List<PeerDestination>>();

		private static readonly List<ZDO> Candidates = new List<ZDO>();

		internal static void Track(ZDOID remotePortal)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (remotePortal != ZDOID.None && TrackedRemotePortals.Add(remotePortal))
			{
				_dirty = true;
			}
		}

		internal static void Untrack(ZDOID remotePortal)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			if (remotePortal != ZDOID.None && TrackedRemotePortals.Remove(remotePortal))
			{
				DestinationComplete.Remove(remotePortal);
				LoggedStates.Remove(remotePortal);
				_dirty = true;
			}
		}

		internal static void ClientUpdate()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			if (!_dirty || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer() || ZRoutedRpc.instance == null || Time.time - _lastSendTime < 0.25f)
			{
				return;
			}
			long serverPeerID = ZRoutedRpc.instance.GetServerPeerID();
			if (serverPeerID == 0L)
			{
				return;
			}
			_dirty = false;
			_lastSendTime = Time.time;
			DestinationComplete.Clear();
			ZPackage val = new ZPackage();
			int num = Mathf.Min(TrackedRemotePortals.Count, 8);
			val.Write(num);
			int num2 = 0;
			foreach (ZDOID trackedRemotePortal in TrackedRemotePortals)
			{
				if (num2++ >= num)
				{
					break;
				}
				val.Write(trackedRemotePortal);
			}
			ZRoutedRpc.instance.InvokeRoutedRPC(serverPeerID, "OttoBifrostSetDestinations", new object[1] { val });
			ForceReferencePositionSend();
		}

		internal static void ForceReferencePositionSend()
		{
			if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer())
			{
				ZNet.instance.m_periodicSendTimer = 2f;
			}
		}

		internal static bool IsDestinationComplete(ZDOID remotePortal)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer())
			{
				return true;
			}
			bool value;
			return DestinationComplete.TryGetValue(remotePortal, out value) && value;
		}

		internal static bool IsDestinationComplete(Vector3 teleportTarget)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer())
			{
				return true;
			}
			if (ZDOMan.instance == null)
			{
				return false;
			}
			float num = 25f;
			foreach (KeyValuePair<ZDOID, bool> item in DestinationComplete)
			{
				if (!item.Value)
				{
					continue;
				}
				ZDO zDO = ZDOMan.instance.GetZDO(item.Key);
				if (zDO != null)
				{
					Vector3 val = zDO.GetPosition() - teleportTarget;
					if (((Vector3)(ref val)).sqrMagnitude <= num)
					{
						return true;
					}
				}
			}
			return false;
		}

		internal static void OnDestinationState(long sender, ZPackage pkg)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0086: 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 && sender == ZRoutedRpc.instance.GetServerPeerID())
			{
				ZDOID val = pkg.ReadZDOID();
				bool flag = pkg.ReadBool();
				if (TrackedRemotePortals.Contains(val))
				{
					DestinationComplete[val] = flag;
				}
				if (PerfStats.Enabled && (!LoggedStates.TryGetValue(val, out var value) || value != flag))
				{
					LoggedStates[val] = flag;
					OttoBifrostPlugin.Log.LogInfo((object)string.Format("Destination {0}: server reports {1}", val, flag ? "complete" : "still sending"));
				}
			}
		}

		internal static int CountKnownObjects(Vector3 point)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			ZDOMan instance = ZDOMan.instance;
			if (instance == null)
			{
				return 0;
			}
			Vector2s zone = ZoneSystem.GetZone(point);
			int num = 0;
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					SectorIndex val = ZoneSystem.SectorToIndex(zone.x + j, zone.y + i);
					if (val.Sector < instance.m_objectsBySector.Length)
					{
						num += instance.m_objectsBySector[val.Sector]?.Count ?? 0;
					}
					if (instance.m_portalObjects.TryGetValue(val, out var value))
					{
						num += value.Count;
					}
				}
			}
			return num;
		}

		internal static void OnSetDestinations(long sender, ZPackage pkg)
		{
			//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)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || ZNet.instance.GetPeer(sender) == null)
			{
				return;
			}
			List<PeerDestination> list = new List<PeerDestination>();
			int num;
			try
			{
				num = Mathf.Min(pkg.ReadInt(), 8);
				for (int i = 0; i < num; i++)
				{
					ZDOID val = pkg.ReadZDOID();
					ZDO zDO = ZDOMan.instance.GetZDO(val);
					if (zDO != null && Portals.IsPortal(zDO))
					{
						ZDO zDO2 = ZDOMan.instance.GetZDO(zDO.GetConnectionZDOID((ConnectionType)1));
						if (zDO2 != null)
						{
							list.Add(new PeerDestination(val, ZoneSystem.GetZone(zDO.GetPosition()), zDO2.GetPosition()));
						}
					}
				}
			}
			catch (Exception ex)
			{
				OttoBifrostPlugin.Log.LogWarning((object)$"Bad destination list from peer {sender}: {ex.Message}");
				return;
			}
			if (list.Count == 0)
			{
				PeerDestinations.Remove(sender);
			}
			else
			{
				PeerDestinations[sender] = list;
			}
			if (PerfStats.Enabled)
			{
				OttoBifrostPlugin.Log.LogInfo((object)$"Destinations from peer {sender}: {list.Count} of {num} accepted");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZDOMan), "CreateSyncList")]
		private static void ZDOManCreateSyncListPostfix(ZDOMan __instance, ZDOPeer peer, List<ZDO> toSync)
		{
			//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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			if (PeerDestinations.Count == 0 || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || !PeerDestinations.TryGetValue(peer.m_peer.m_uid, out List<PeerDestination> value))
			{
				return;
			}
			long start = PerfStats.Begin();
			Vector3 refPos = peer.m_peer.GetRefPos();
			float num = 900f;
			HashSet<SectorIndex> visitedSectorIndices = __instance.m_visitedSectorIndices;
			int num2 = 0;
			foreach (PeerDestination item in value)
			{
				Vector3 val = item.sourcePortalPos - refPos;
				if (((Vector3)(ref val)).sqrMagnitude > num)
				{
					continue;
				}
				Candidates.Clear();
				for (int i = -1; i <= 1; i++)
				{
					for (int j = -1; j <= 1; j++)
					{
						__instance.FindObjects(new Vector2s(item.remoteZone.x + j, item.remoteZone.y + i), Candidates, visitedSectorIndices);
					}
				}
				int num3 = 0;
				foreach (ZDO candidate in Candidates)
				{
					if (peer.ShouldSend(candidate))
					{
						toSync.Add(candidate);
						num3++;
					}
				}
				num2 += num3;
				ReportState(peer.m_peer.m_uid, item, num3);
			}
			Candidates.Clear();
			if (PerfStats.Enabled)
			{
				PerfStats.ServerObjectsAppended += num2;
				PerfStats.ServerSyncTicks += PerfStats.Elapsed(start);
			}
		}

		private static void ReportState(long peerUid, PeerDestination dest, int waiting)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			bool? flag = ((waiting == 0) ? new bool?(true) : ((waiting >= 16) ? new bool?(false) : dest.ReportedComplete));
			if (flag.HasValue && flag != dest.ReportedComplete && ZRoutedRpc.instance != null)
			{
				dest.ReportedComplete = flag;
				ZPackage val = new ZPackage();
				val.Write(dest.remoteId);
				val.Write(flag.Value);
				ZRoutedRpc.instance.InvokeRoutedRPC(peerUid, "OttoBifrostDestinationState", new object[1] { val });
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZDOMan), "RemovePeer")]
		private static void ZDOManRemovePeerPostfix(ZNetPeer netPeer)
		{
			if (netPeer != null)
			{
				PeerDestinations.Remove(netPeer.m_uid);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Game), "Start")]
		private static void GameStartPostfix()
		{
			ZRoutedRpc.instance.Register<ZPackage>("OttoBifrostSetDestinations", (Action<long, ZPackage>)OnSetDestinations);
			ZRoutedRpc.instance.Register<ZPackage>("OttoBifrostDestinationState", (Action<long, ZPackage>)OnDestinationState);
		}

		internal static void Clear()
		{
			TrackedRemotePortals.Clear();
			DestinationComplete.Clear();
			LoggedStates.Clear();
			_dirty = false;
			_lastSendTime = float.MinValue;
			PeerDestinations.Clear();
			Candidates.Clear();
		}
	}
	[HarmonyPatch]
	internal static class PerfStats
	{
		private const float ReportInterval = 5f;

		internal static bool Enabled;

		private static float _windowTime;

		private static int _frames;

		private static float _worstFrame;

		internal static int PreviewRenders;

		internal static long PreviewRenderTicks;

		internal static long PreviewRenderMaxTicks;

		internal static int ZonesSpawned;

		internal static int ZoneWaits;

		internal static float ZoneWaitTotal;

		internal static float ZoneWaitMax;

		internal static int TerrainQueueMax;

		private static int _terrainBuilds;

		private static long _terrainBuildTicks;

		internal static long ZonePatchTicks;

		internal static long SectorPatchTicks;

		internal static int ForcedCreates;

		internal static long CreatePatchTicks;

		internal static int NearestSwitches;

		internal static int HeightmapForceCalls;

		internal static int HeightmapsForced;

		internal static long HeightmapForceTicks;

		internal static long HeightmapForceMaxTicks;

		internal static int ServerObjectsAppended;

		internal static long ServerSyncTicks;

		internal static long Begin()
		{
			if (!Enabled)
			{
				return 0L;
			}
			return Stopwatch.GetTimestamp();
		}

		internal static long Elapsed(long start)
		{
			if (start != 0L)
			{
				return Stopwatch.GetTimestamp() - start;
			}
			return 0L;
		}

		private static string Ms(long ticks)
		{
			return ((double)ticks * 1000.0 / (double)Stopwatch.Frequency).ToString("F1");
		}

		internal static void Tick(float unscaledDeltaTime, bool enabled)
		{
			if (enabled != Enabled)
			{
				Enabled = enabled;
				Reset();
			}
			if (enabled)
			{
				_frames++;
				_windowTime += unscaledDeltaTime;
				if (unscaledDeltaTime > _worstFrame)
				{
					_worstFrame = unscaledDeltaTime;
				}
				if (!(_windowTime < 5f))
				{
					float num = _windowTime * 1000f / (float)_frames;
					string arg = ((PreviewRenders > 0) ? Ms(PreviewRenderTicks / PreviewRenders) : "0.0");
					float num2 = ((ZoneWaits > 0) ? (ZoneWaitTotal / (float)ZoneWaits) : 0f);
					long num3 = Interlocked.Read(in _terrainBuildTicks);
					double num4 = (double)num3 * 100.0 / (double)Stopwatch.Frequency / (double)_windowTime;
					OttoBifrostPlugin.Log.LogInfo((object)($"Perf {_windowTime:F1}s: frames {_frames} avg {num:F1} ms worst {_worstFrame * 1000f:F1} ms" + $" | destinations {Destinations.Active.Length}, nearest switches {NearestSwitches}" + $" | preview renders {PreviewRenders} avg {arg} ms max {Ms(PreviewRenderMaxTicks)} ms" + $" | zones spawned {ZonesSpawned} (zone patch {Ms(ZonePatchTicks)} ms)" + $", wait at front of line avg {num2:F2} s max {ZoneWaitMax:F2} s over {ZoneWaits}" + $" | terrain thread {Interlocked.Exchange(ref _terrainBuilds, 0)} builds, {Ms(num3)} ms, busy {num4:F0}%, queue max {TerrainQueueMax}" + " | sector patch " + Ms(SectorPatchTicks) + " ms" + $" | forced creates {ForcedCreates} ({Ms(CreatePatchTicks)} ms)" + $" | heightmap force {HeightmapForceCalls} calls, {HeightmapsForced} rebuilt, {Ms(HeightmapForceTicks)} ms total, max {Ms(HeightmapForceMaxTicks)} ms" + $" | server appended {ServerObjectsAppended} objects ({Ms(ServerSyncTicks)} ms)" + $" | client objects {ZDOMan.instance?.m_objectsByID.Count ?? 0}, received {ZDOMan.instance?.m_zdosRecvLastSec ?? 0}/s"));
					Reset();
				}
			}
		}

		internal static void AddPreviewRender(long start)
		{
			long num = Elapsed(start);
			if (num != 0L)
			{
				PreviewRenders++;
				PreviewRenderTicks += num;
				if (num > PreviewRenderMaxTicks)
				{
					PreviewRenderMaxTicks = num;
				}
			}
		}

		internal static void AddZoneWait(float seconds)
		{
			ZoneWaits++;
			ZoneWaitTotal += seconds;
			if (seconds > ZoneWaitMax)
			{
				ZoneWaitMax = seconds;
			}
		}

		private static void Reset()
		{
			_windowTime = 0f;
			_frames = 0;
			_worstFrame = 0f;
			PreviewRenders = 0;
			PreviewRenderTicks = 0L;
			PreviewRenderMaxTicks = 0L;
			ZonesSpawned = 0;
			ZoneWaits = 0;
			ZoneWaitTotal = 0f;
			ZoneWaitMax = 0f;
			TerrainQueueMax = 0;
			Interlocked.Exchange(ref _terrainBuilds, 0);
			Interlocked.Exchange(ref _terrainBuildTicks, 0L);
			ZonePatchTicks = 0L;
			SectorPatchTicks = 0L;
			ForcedCreates = 0;
			CreatePatchTicks = 0L;
			NearestSwitches = 0;
			HeightmapForceCalls = 0;
			HeightmapsForced = 0;
			HeightmapForceTicks = 0L;
			HeightmapForceMaxTicks = 0L;
			ServerObjectsAppended = 0;
			ServerSyncTicks = 0L;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(HeightmapBuilder), "Build")]
		private static void HeightmapBuilderBuildPrefix(out long __state)
		{
			__state = Begin();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(HeightmapBuilder), "Build")]
		private static void HeightmapBuilderBuildPostfix(long __state)
		{
			long num = Elapsed(__state);
			if (num != 0L)
			{
				Interlocked.Increment(ref _terrainBuilds);
				Interlocked.Add(ref _terrainBuildTicks, num);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Heightmap), "ForceGenerateAll")]
		private static void HeightmapForceGenerateAllPrefix(out long __state)
		{
			__state = Begin();
			if (__state == 0L)
			{
				return;
			}
			HeightmapForceCalls++;
			foreach (Heightmap s_heightmap in Heightmap.s_heightmaps)
			{
				if (s_heightmap.HaveQueuedRebuild())
				{
					HeightmapsForced++;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Heightmap), "ForceGenerateAll")]
		private static void HeightmapForceGenerateAllPostfix(long __state)
		{
			long num = Elapsed(__state);
			if (num != 0L)
			{
				HeightmapForceTicks += num;
				if (num > HeightmapForceMaxTicks)
				{
					HeightmapForceMaxTicks = num;
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class PortalPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(TeleportWorld), "Awake")]
		private static void TeleportWorldAwakePostfix(TeleportWorld __instance)
		{
			if (!Player.IsPlacementGhost(((Component)__instance).gameObject) && (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()))
			{
				((Component)__instance).gameObject.AddComponent<DestinationLoader>();
				((Component)__instance).gameObject.AddComponent<PortalWindow>();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZNetScene), "OnDestroy")]
		private static void ZNetSceneOnDestroyPostfix()
		{
			Destinations.Clear();
			TeleportPatches.Reset();
			DestinationSync.Clear();
		}
	}
	[HarmonyPatch]
	internal static class TeleportPatches
	{
		private const float SkipVanillaWait = 2.1f;

		private const float MinimumTeleportTime = 0.5f;

		private const float FloorSearchTimeout = 3f;

		private const float FallbackToVanillaTime = 8f;

		private const float ServerReactionTime = 1f;

		private const float ArrivalStableTime = 0.5f;

		private const float PreloadedTolerance = 10f;

		private const float ArrivalHoldSeconds = 5f;

		private static bool _awaitingArrival;

		private static bool _fastTrip;

		private static bool _serverComplete;

		private static float _startedAt;

		private static float _movedAt = -1f;

		private static int _arrivalObjects = -1;

		private static int _arrivalObjectsAtMove;

		private static float _arrivalChangedAt;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "TeleportTo")]
		private static void PlayerTeleportToPostfix(Player __instance, Vector3 pos, bool distantTeleport, bool __result)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (__result && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				_awaitingArrival = true;
				Destinations.BeginTeleport();
				_fastTrip = distantTeleport && OttoBifrostPlugin.FastTeleport.Value && Destinations.IsNear(pos, 10f);
				_serverComplete = DestinationSync.IsDestinationComplete(pos);
				_startedAt = Time.time;
				_movedAt = -1f;
				_arrivalObjects = -1;
				if (PerfStats.Enabled)
				{
					OttoBifrostPlugin.Log.LogInfo((object)$"Teleport start: fast path {_fastTrip}, server reports destination complete {_serverComplete}");
				}
				if (_fastTrip)
				{
					__instance.m_teleportTimer = 2.1f;
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "UpdateTeleport")]
		private static bool PlayerUpdateTeleportPrefix(Player __instance, float dt)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: 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_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			if (!_fastTrip || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !__instance.m_teleporting)
			{
				return true;
			}
			if ((Object)(object)ZoneSystem.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || !OttoBifrostPlugin.FastTeleport.Value)
			{
				_fastTrip = false;
				return true;
			}
			__instance.m_teleportCooldown = 0f;
			float num = (__instance.m_teleportTimer = 2.1f + (Time.time - _startedAt));
			if (num <= 0.5f)
			{
				return false;
			}
			Vector3 teleportTargetPos = __instance.m_teleportTargetPos;
			HoldAtTarget(__instance);
			if (_movedAt < 0f)
			{
				_movedAt = Time.time;
				MovePlayerZdo(__instance, teleportTargetPos);
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					ZNet.instance.SetReferencePosition(teleportTargetPos);
					DestinationSync.ForceReferencePositionSend();
				}
			}
			TrackArrivalObjects(teleportTargetPos);
			bool flag = _serverComplete || (Time.time - _movedAt >= 1f && Time.time - _arrivalChangedAt >= 0.5f);
			bool flag2 = ZoneLoadPatches.AreNearObjectsBuilt(teleportTargetPos, Vector3.forward, 40f);
			float num2 = default(float);
			bool flag3 = ZoneSystem.instance.FindFloor(teleportTargetPos, ref num2);
			if (flag2 && flag && (flag3 || num > 3f))
			{
				if (flag3)
				{
					((Component)__instance).transform.position = new Vector3(teleportTargetPos.x, num2, teleportTargetPos.z);
				}
				__instance.m_teleportTimer = 0f;
				__instance.m_teleporting = false;
				((Character)__instance).ResetCloth();
				_fastTrip = false;
				LogOutcome("finished", teleportTargetPos, flag2, flag, flag3);
				return false;
			}
			if (num > 8f)
			{
				_fastTrip = false;
				LogOutcome("handed over to vanilla", teleportTargetPos, flag2, flag, flag3);
				return true;
			}
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "UpdateTeleport")]
		private static void PlayerUpdateTeleportPostfix(Player __instance)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (_awaitingArrival && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !__instance.m_teleporting)
			{
				_awaitingArrival = false;
				Destinations.EndTeleport(((Component)__instance).transform.position, 5f);
			}
		}

		private static void HoldAtTarget(Player player)
		{
			//IL_0007: 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_001d: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			((Component)player).transform.SetPositionAndRotation(player.m_teleportTargetPos, player.m_teleportTargetRot);
			((Character)player).m_body.linearVelocity = Vector3.zero;
			((Character)player).m_maxAirAltitude = player.m_teleportTargetPos.y;
			if ((Object)(object)EnvMan.instance != (Object)null)
			{
				EnvMan.instance.ForceInstantEnvironmentSwitch();
			}
			((Character)player).SetLookDir(player.m_teleportTargetRot * Vector3.forward, 0f);
		}

		private static void MovePlayerZdo(Player player, Vector3 target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			((Character)player).m_body.position = target;
			ZSyncTransform component = ((Component)player).GetComponent<ZSyncTransform>();
			if ((Object)(object)component != (Object)null)
			{
				component.SyncNow();
			}
		}

		private static void TrackArrivalObjects(Vector3 target)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			int num = DestinationSync.CountKnownObjects(target);
			if (num != _arrivalObjects)
			{
				if (_arrivalObjects < 0)
				{
					_arrivalObjectsAtMove = num;
				}
				_arrivalObjects = num;
				_arrivalChangedAt = Time.time;
			}
		}

		private static void LogOutcome(string outcome, Vector3 target, bool nearBuilt, bool dataSettled, bool floorFound)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (PerfStats.Enabled)
			{
				bool flag = ZNetScene.instance.IsAreaReady(target);
				OttoBifrostPlugin.Log.LogInfo((object)($"Teleport {outcome} after {Time.time - _startedAt:F2} s: server reports complete {_serverComplete}, " + $"near objects built {nearBuilt}, area ready {flag}, data settled {dataSettled}, floor {floorFound}, " + $"arrival objects {_arrivalObjects} ({_arrivalObjects - _arrivalObjectsAtMove} received since the move)"));
			}
		}

		internal static void Reset()
		{
			_awaitingArrival = false;
			_fastTrip = false;
			_serverComplete = false;
			_movedAt = -1f;
			_arrivalObjects = -1;
		}
	}
	[HarmonyPatch]
	internal static class ZoneLoadPatches
	{
		private readonly struct Candidate
		{
			public readonly ZDO Zdo;

			public readonly bool Portal;

			public readonly bool Behind;

			public readonly float DistanceSqr;

			public Candidate(ZDO zdo, bool portal, bool behind, float distanceSqr)
			{
				Zdo = zdo;
				Portal = portal;
				Behind = behind;
				DistanceSqr = distanceSqr;
			}
		}

		internal enum NearState
		{
			ZonesMissing,
			ObjectsMissing,
			Built
		}

		private const float PrimeInterval = 0.2f;

		private const float MaxPrimeInterval = 2f;

		private const int CreatesPerPass = 20;

		internal const float PrimeRadius = 40f;

		private const int TerrainLookahead = 4;

		private const int TerrainQueueLimit = 8;

		internal const float BehindAllowance = 2f;

		private static readonly List<ZDO> Candidates = new List<ZDO>();

		private static readonly HashSet<SectorIndex> CandidateSectors = new HashSet<SectorIndex>();

		private static readonly List<Candidate> Queue = new List<Candidate>();

		private static readonly Dictionary<Vector2s, ObjectType> UnfinishedZones = new Dictionary<Vector2s, ObjectType>();

		private static readonly List<ZDO> NearObjects = new List<ZDO>();

		private static readonly HashSet<SectorIndex> NearSectors = new HashSet<SectorIndex>();

		private static readonly List<Vector2s> MissingZones = new List<Vector2s>();

		private static Vector2s _frontZone;

		private static float _frontSince = -1f;

		private static Heightmap? _zoneHeightmap;

		private static float _nextPrimeCheck;

		private static float _nextPrimeTime;

		private static float _primeWait = 0.2f;

		private static Destination[]? _primedDestinations;

		private static int _primedWorkKey;

		private static bool _inAreaReadyCheck;

		private static readonly Comparison<Candidate> ByPriority = delegate(Candidate a, Candidate b)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected I4, but got Unknown
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected I4, but got Unknown
			int num = ((int)b.Zdo.Type).CompareTo((int)a.Zdo.Type);
			if (num != 0)
			{
				return num;
			}
			if (a.Portal != b.Portal)
			{
				if (!a.Portal)
				{
					return 1;
				}
				return -1;
			}
			if (a.Behind != b.Behind)
			{
				if (!a.Behind)
				{
					return -1;
				}
				return 1;
			}
			float distanceSqr = a.DistanceSqr;
			return distanceSqr.CompareTo(b.DistanceSqr);
		};

		private static bool IsZoneLoaded(Vector2s zone)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZoneSystem.instance != (Object)null)
			{
				return ZoneSystem.instance.m_zones.ContainsKey(zone);
			}
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZNetScene), "PointInsideActiveArea")]
		private static void ZNetScenePointInsideActiveAreaPostfix(Vector3 point, ref bool __result)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (!__result && Destinations.Any && Destinations.Covers(ZoneSystem.GetZone(point)))
			{
				__result = true;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZDOMan), "FindSectorObjects")]
		private static void ZDOManFindSectorObjectsPostfix(ZDOMan __instance, List<ZDO> sectorObjects)
		{
			//IL_005c: 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_007d: 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)
			Destination[] active = Destinations.Active;
			if (active.Length == 0 || (Object)(object)ZoneSystem.instance == (Object)null || _inAreaReadyCheck)
			{
				return;
			}
			long start = PerfStats.Begin();
			HashSet<SectorIndex> visitedSectorIndices = __instance.m_visitedSectorIndices;
			Destination[] array = active;
			Vector2s val = default(Vector2s);
			for (int i = 0; i < array.Length; i++)
			{
				Destination destination = array[i];
				for (int j = -destination.Radius; j <= destination.Radius; j++)
				{
					for (int k = -destination.Radius; k <= destination.Radius; k++)
					{
						((Vector2s)(ref val))..ctor(destination.Zone.x + k, destination.Zone.y + j);
						if (IsZoneLoaded(val))
						{
							__instance.FindObjects(val, sectorObjects, visitedSectorIndices);
						}
					}
				}
			}
			PerfStats.SectorPatchTicks += PerfStats.Elapsed(start);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZDOMan), "FindDistantObjects")]
		private static bool ZDOManFindDistantObjectsPrefix(Vector2s sector)
		{
			//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)
			if (!_inAreaReadyCheck && Destinations.Any && Destinations.Covers(sector))
			{
				return !IsZoneLoaded(sector);
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZoneSystem), "CreateLocalZones")]
		private static void ZoneSystemCreateLocalZonesPostfix(ZoneSystem __instance, ref bool __result)
		{
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: 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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			Destination[] active = Destinations.Active;
			if (active.Length == 0)
			{
				return;
			}
			long start = PerfStats.Begin();
			int num = 0;
			Destination[] array = active;
			for (int i = 0; i < array.Length; i++)
			{
				Destination destination = array[i];
				num = Mathf.Max(num, destination.Radius);
			}
			MissingZones.Clear();
			AddMissingNearZones(__instance, active);
			Vector2s val = default(Vector2s);
			for (int j = 0; j <= num; j++)
			{
				array = active;
				for (int i = 0; i < array.Length; i++)
				{
					Destination destination2 = array[i];
					if (destination2.Radius < j)
					{
						continue;
					}
					for (int k = -j; k <= j; k++)
					{
						for (int l = -j; l <= j; l++)
						{
							if (Mathf.Max(Mathf.Abs(l), Mathf.Abs(k)) == j)
							{
								((Vector2s)(ref val))..ctor(destination2.Zone.x + l, destination2.Zone.y + k);
								if (__instance.m_zones.TryGetValue(val, out var value))
								{
									value.m_ttl = 0f;
								}
								else
								{
									AddMissing(val);
								}
							}
						}
					}
				}
			}
			if (MissingZones.Count == 0)
			{
				_frontSince = -1f;
			}
			else if (_frontSince < 0f || !(MissingZones[0] == _frontZone))
			{
				_frontZone = MissingZones[0];
				_frontSince = Time.time;
			}
			if (!__result && MissingZones.Count > 0)
			{
				if (__instance.PokeLocalZone(MissingZones[0]))
				{
					__result = true;
					if (PerfStats.Enabled)
					{
						PerfStats.ZonesSpawned++;
						PerfStats.AddZoneWait(Time.time - _frontSince);
					}
					_frontSince = -1f;
				}
				RequestTerrainAhead(__instance);
			}
			PerfStats.ZonePatchTicks += PerfStats.Elapsed(start);
		}

		private static void AddMissingNearZones(ZoneSystem zoneSystem, Destination[] destinations)
		{
			//IL_0015: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			Destination[] array = destinations;
			for (int i = 0; i < array.Length; i++)
			{
				Destination destination = array[i];
				if (!zoneSystem.m_zones.ContainsKey(destination.Zone))
				{
					AddMissing(destination.Zone);
				}
			}
			array = destinations;
			Vector2s val = default(Vector2s);
			for (int i = 0; i < array.Length; i++)
			{
				Destination destination2 = array[i];
				for (int j = -1; j <= 1; j++)
				{
					for (int k = -1; k <= 1; k++)
					{
						((Vector2s)(ref val))..ctor(destination2.Zone.x + k, destination2.Zone.y + j);
						if (!zoneSystem.m_zones.ContainsKey(val) && WithinPrimeRadius(zoneSystem, val, destination2.Position))
						{
							AddMissing(val);
						}
					}
				}
			}
		}

		private static void AddMissing(Vector2s zone)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (MissingZones.Count <= 4 && !MissingZones.Contains(zone))
			{
				MissingZones.Add(zone);
			}
		}

		private static void RequestTerrainAhead(ZoneSystem zoneSystem)
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00b3: Unknown result type (might be due to invalid IL or missing references)
			HeightmapBuilder instance = HeightmapBuilder.instance;
			if (instance == null || WorldGenerator.instance == null || MissingZones.Count < 2)
			{
				return;
			}
			if ((Object)(object)_zoneHeightmap == (Object)null)
			{
				_zoneHeightmap = zoneSystem.m_zonePrefab.GetComponentInChildren<Heightmap>();
			}
			if ((Object)(object)_zoneHeightmap == (Object)null)
			{
				return;
			}
			lock (instance.m_lock)
			{
				if (PerfStats.Enabled && instance.m_toBuild.Count > PerfStats.TerrainQueueMax)
				{
					PerfStats.TerrainQueueMax = instance.m_toBuild.Count;
				}
				int num = 8 - instance.m_toBuild.Count - instance.m_ready.Count;
				for (int i = 1; i < MissingZones.Count; i++)
				{
					if (num <= 0)
					{
						break;
					}
					Vector2s val = MissingZones[i];
					if (!instance.IsTerrainReady(ZoneSystem.GetZonePos(val), _zoneHeightmap.m_width, _zoneHeightmap.m_scale, _zoneHeightmap.IsDistantLod, WorldGenerator.instance))
					{
						num--;
					}
				}
			}
		}

		private static bool WithinPrimeRadius(ZoneSystem zoneSystem, Vector2s zone, Vector3 point)
		{
			//IL_000d: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			float num = zoneSystem.m_zoneSize * 0.5f;
			Vector3 zonePos = ZoneSystem.GetZonePos(zone);
			float num2 = Mathf.Max(Mathf.Abs(point.x - zonePos.x) - num, 0f);
			float num3 = Mathf.Max(Mathf.Abs(point.z - zonePos.z) - num, 0f);
			return num2 * num2 + num3 * num3 <= 1600f;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZNetScene), "IsAreaReady")]
		private static void ZNetSceneIsAreaReadyPrefix()
		{
			_inAreaReadyCheck = true;
		}

		[HarmonyFinalizer]
		[HarmonyPatch(typeof(ZNetScene), "IsAreaReady")]
		private static void ZNetSceneIsAreaReadyFinalizer()
		{
			_inAreaReadyCheck = false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZNetScene), "CreateDestroyObjects")]
		private static void ZNetSceneCreateDestroyObjectsPostfix(ZNetScene __instance)
		{
			Destination[] active = Destinations.Active;
			ZoneSystem instance = ZoneSystem.instance;
			if (active.Length == 0 || ZDOMan.instance == null || (Object)(object)instance == (Object)null || Time.time < _nextPrimeCheck)
			{
				return;
			}
			_nextPrimeCheck = Time.time + 0.2f;
			int num = WorkKey(active, instance);
			if (active != _primedDestinations || num != _primedWorkKey)
			{
				_primedDestinations = active;
				_primedWorkKey = num;
				_primeWait = 0.2f;
			}
			else if (Time.time < _nextPrimeTime)
			{
				return;
			}
			long start = PerfStats.Begin();
			int budget = 20;
			Destination[] array = active;
			foreach (Destination destination in array)
			{
				CreateNearDestination(__instance, instance, destination, ref budget);
				if (budget == 0)
				{
					break;
				}
			}
			_primeWait = ((budget < 20) ? 0.2f : Mathf.Min(_primeWait * 2f, 2f));
			_nextPrimeTime = Time.time + _primeWait;
			if (PerfStats.Enabled)
			{
				PerfStats.ForcedCreates += 20 - budget;
				PerfStats.CreatePatchTicks += PerfStats.Elapsed(start);
			}
		}

		private static void CreateNearDestination(ZNetScene scene, ZoneSystem zoneSystem, Destination destination, ref int budget)
		{
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: 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)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Invalid comparison between Unknown and I4
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			float num = 42f * 42f;
			Candidates.Clear();
			CandidateSectors.Clear();
			Vector2s val = default(Vector2s);
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					((Vector2s)(ref val))..ctor(destination.Zone.x + j, destination.Zone.y + i);
					if (zoneSystem.m_zones.ContainsKey(val))
					{
						ZDOMan.instance.FindObjects(val, Candidates, CandidateSectors);
					}
				}
			}
			Queue.Clear();
			foreach (ZDO candidate in Candidates)
			{
				if (candidate.IsValid() && !scene.m_instances.ContainsKey(candidate) && scene.IsPrefabZDOValid(candidate))
				{
					Vector3 val2 = candidate.GetPosition() - destination.Position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if ((int)candidate.Type == 3 || !(sqrMagnitude > num))
					{
						val2.y = 0f;
						Queue.Add(new Candidate(candidate, Portals.IsPortal(candidate), Vector3.Dot(val2, destination.Forward) < -2f, sqrMagnitude));
					}
				}
			}
			Candidates.Clear();
			if (Queue.Count == 0)
			{
				return;
			}
			Queue.Sort(ByPriority);
			UnfinishedZones.Clear();
			foreach (Candidate item in Queue)
			{
				if (budget == 0)
				{
					break;
				}
				ZDO zdo = item.Zdo;
				Vector2s sector = zdo.GetSector();
				if (UnfinishedZones.TryGetValue(sector, out var value) && zdo.Type < value)
				{
					continue;
				}
				if (!zoneSystem.IsZoneReadyForType(sector, zdo.Type))
				{
					UnfinishedZones[sector] = zdo.Type;
					continue;
				}
				try
				{
					if ((Object)(object)scene.CreateObject(zdo) != (Object)null)
					{
						budget--;
					}
				}
				catch (Exception ex)
				{
					OttoBifrostPlugin.Log.LogDebug((object)$"Could not create {zdo.m_uid} near a destination: {ex.Message}");
				}
			}
			Queue.Clear();
		}

		private static int WorkKey(Destination[] destinations, ZoneSystem zoneSystem)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			int num = destinations.Length;
			for (int i = 0; i < destinations.Length; i++)
			{
				Destination destination = destinations[i];
				for (int j = -1; j <= 1; j++)
				{
					for (int k = -1; k <= 1; k++)
					{
						bool flag = zoneSystem.m_zones.ContainsKey(new Vector2s(destination.Zone.x + k, destination.Zone.y + j));
						num = num * 31 + (flag ? 1 : 0);
					}
				}
				num = num * 31 + DestinationSync.CountKnownObjects(destination.Position);
			}
			return num;
		}

		internal static bool AreNearObjectsBuilt(Vector3 origin, Vector3 forward, float behindAllowance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			ZDO blocker;
			return GetNearState(origin, forward, behindAllowance, out blocker) == NearState.Built;
		}

		internal static NearState GetNearState(Vector3 origin, Vector3 forward, float behindAllowance, out ZDO? blocker)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: 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)
			//IL_010b: Invalid comparison between Unknown and I4
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Invalid comparison between Unknown and I4
			//IL_012d: 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)
			blocker = null;
			ZoneSystem instance = ZoneSystem.instance;
			ZNetScene instance2 = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || ZDOMan.instance == null)
			{
				return NearState.ZonesMissing;
			}
			float num = 1600f;
			Vector2s zone = ZoneSystem.GetZone(origin);
			NearObjects.Clear();
			NearSectors.Clear();
			Vector2s val = default(Vector2s);
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					((Vector2s)(ref val))..ctor(zone.x + j, zone.y + i);
					if (WithinPrimeRadius(instance, val, origin))
					{
						if (!instance.m_zones.ContainsKey(val))
						{
							NearObjects.Clear();
							return NearState.ZonesMissing;
						}
						ZDOMan.instance.FindObjects(val, NearObjects, NearSectors);
					}
				}
			}
			foreach (ZDO nearObject in NearObjects)
			{
				if (!nearObject.IsValid() || !instance2.IsPrefabZDOValid(nearObject) || instance2.HaveInstance(nearObject))
				{
					continue;
				}
				Vector3 val2 = nearObject.GetPosition() - origin;
				if ((int)nearObject.Type == 3 || !(((Vector3)(ref val2)).sqrMagnitude > num))
				{
					val2.y = 0f;
					if ((int)nearObject.Type == 3 || !(Vector3.Dot(val2, forward) < 0f - behindAllowance))
					{
						blocker = nearObject;
						break;
					}
				}
			}
			NearObjects.Clear();
			if (blocker != null)
			{
				return NearState.ObjectsMissing;
			}
			return NearState.Built;
		}

		internal static string Describe(ZDO zdo, Vector3 origin)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(zdo.GetPrefab()) : null);
			Vector3 val2 = zdo.GetPosition() - origin;
			float y = val2.y;
			val2.y = 0f;
			bool flag = (Object)(object)ZoneSystem.instance == (Object)null || ZoneSystem.instance.IsZoneReadyForType(zdo.GetSector(), zdo.Type);
			return $"{(((Object)(object)val != (Object)null) ? ((Object)val).name : zdo.GetPrefab().ToString())} ({zdo.Type}, {((Vector3)(ref val2)).magnitude:F0} m across, " + string.Format("{0:F0} m up{1})", y, flag ? "" : ", its zone is still loading a location");
		}
	}
}
namespace OttoBifrost.Components
{
	public sealed class DestinationLoader : MonoBehaviour
	{
		private const float ReachDistance = 15f;

		private const float CheckInterval = 0.2f;

		private const float SecondsPerRing = 0.4f;

		private TeleportWorld _portal;

		private ZDOID _portalId = ZDOID.None;

		private ZDOID _farEndId = ZDOID.None;

		private float _requestedAt;

		private float _nextCheck;

		private void Awake()
		{
			_portal = ((Component)this).GetComponent<TeleportWorld>();
			_nextCheck = Time.time + Random.value * 0.2f;
		}

		private void Update()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time < _nextCheck)
			{
				return;
			}
			_nextCheck = Time.time + 0.2f;
			Player localPlayer = Player.m_localPlayer;
			ZDO val = Portals.ZdoOf(_portal);
			ZDO val2 = ((val != null) ? Portals.FarEnd(val) : null);
			if ((Object)(object)localPlayer == (Object)null || val == null || val2 == null || !OttoBifrostPlugin.PreloadDestinations.Value)
			{
				Release();
				return;
			}
			Vector3 val3 = (((Object)(object)_portal.m_proximityRoot != (Object)null) ? _portal.m_proximityRoot.position : ((Component)this).transform.position);
			float num = Vector3.Distance(((Component)localPlayer).transform.position, val3);
			if (num > 15f)
			{
				Release();
				return;
			}
			if (val2.m_uid != _farEndId)
			{
				Release();
				_portalId = val.m_uid;
				_farEndId = val2.m_uid;
				_requestedAt = Time.time;
				DestinationSync.Track(_farEndId);
			}
			int num2 = 1 + (int)((Time.time - _requestedAt) / 0.4f);
			Destinations.Request(_portalId, val2.GetPosition(), val2.GetRotation() * Vector3.forward, Mathf.Min(RadiusFor(num), num2), num);
		}

		private void OnDisable()
		{
			Release();
		}

		private void Release()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (!(_farEndId == ZDOID.None))
			{
				Destinations.Release(_portalId);
				DestinationSync.Untrack(_farEndId);
				_portalId = ZDOID.None;
				_farEndId = ZDOID.None;
			}
		}

		private static int RadiusFor(float distance)
		{
			if (distance <= 5f)
			{
				return 3;
			}
			if (!(distance <= 10f))
			{
				return 1;
			}
			return 2;
		}
	}
	public sealed class PortalWindow : MonoBehaviour
	{
		private enum StaticStage
		{
			None,
			Near,
			Full
		}

		private const float MaxViewDistance = 12f;

		private const int TextureSize = 512;

		private static readonly Vector3 DiscOffset = new Vector3(0f, 1.31f, 0.01f);

		private const float DiscDiameter = 2.85f;

		private const int DiscSegments = 48;

		private const float EveryFrameDistance = 4f;

		private const float FastRateDistance = 8f;

		private const float FastRateInterval = 0.1f;

		private const float SlowRateInterval = 1f / 3f;

		private const float FarClip = 300f;

		private const float NearClip = 0.5f;

		private const float NearClipBlocked = 0.1f;

		private const float CameraRadius = 0.35f;

		private const float WaterClearance = 0.3f;

		private const float StaticEyeHeight = 1.8f;

		private const float StaticPullBack = 1.5f;

		private const float StaticPitch = 8f;

		private const float StaticCheckInterval = 0.2f;

		private const float StaticSettleTime = 1f;

		private const float StaticCaptureDelay = 0.2f;

		private const int RippleRings = 12;

		private const float StaticAlpha = 0.7f;

		private const float RimFadeWidth = 0.08f;

		private const float RippleAmplitude = 0.012f;

		private const float RippleFrequency = 40f;

		private const float RippleSpeed = 3f;

		private const float WaveAmplitude = 0.006f;

		private const float ShimmerFrequency = 9f;

		private const float ShimmerSpeed = 2.2f;

		private const float ShimmerBase = 0.82f;

		private static readonly Color ShimmerTint = new Color(0.92f, 0.97f, 1f);

		private static readonly Vector2 UvCentre = new Vector2(0.5f, 0.5f);

		private static readonly List<PortalWindow> Windows = new List<PortalWindow>();

		private static readonly Quaternion HalfTurn = Quaternion.Euler(0f, 180f, 0f);

		private static PortalWindow? _live;

		private static int _liveFrame = -1;

		private static int _captureFrame = -1;

		private static Mesh? _discMesh;

		private static Mesh? _rippleMesh;

		private static Vector2[] _rippleBase = Array.Empty<Vector2>();

		private static Vector2[] _rippleUv = Array.Empty<Vector2>();

		private static Color[] _rippleColors = Array.Empty<Color>();

		private static int _rippleFrame = -1;

		private static int _blockMask;

		private TeleportWorld _portal;

		private Camera? _camera;

		private RenderTexture? _texture;

		private Material? _material;

		private MeshRenderer? _frontDisc;

		private MeshRenderer? _backDisc;

		private bool _viewerInFront = true;

		private bool _discsRipple;

		private bool _hasFrame;

		private float _nextRenderTime;

		private bool _staticView;

		private StaticStage _captured;

		private ZDOID _frameFarEnd = ZDOID.None;

		private float _nextStaticCheck;

		private int _settleCount = -1;

		private float _settleChangedAt;

		private float _readySince = -1f;

		private float _approachedAt = -1f;

		private float _farFoundAt = -1f;

		private float _nearZonesAt = -1f;

		private float _nearBuiltAt = -1f;

		private string? _lastBlocker;

		private TeleportWorld? _hiddenPortal;

		private Renderer[] _hiddenRenderers = Array.Empty<Renderer>();

		private bool[] _hiddenWasEnabled = Array.Empty<bool>();

		private void Awake()
		{
			_portal = ((Component)this).GetComponent<TeleportWorld>();
		}

		private void OnEnable()
		{
			Windows.Add(this);
		}

		private void OnDisable()
		{
			Windows.Remove(this);
			if ((Object)(object)_live == (Object)(object)this)
			{
				_live = null;
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_camera != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_camera).gameObject);
			}
			if ((Object)(object)_texture != (Object)null)
			{
				_texture.Release();
				Object.Destroy((Object)(object)_texture);
			}
			if ((Object)(object)_material != (Object)null)
			{
				Object.Destroy((Object)(object)_material);
			}
		}

		private void LateUpdate()
		{
			//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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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)
			Camera main = Camera.main;
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)main == (Object)null || (Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			Vector3 eyePoint = ((Character)localPlayer).GetEyePoint();
			bool flag = OttoBifrostPlugin.PreviewMode.Value == OttoBifrostPlugin.PreviewModes.StaticView;
			if (flag != _staticView)
			{
				_staticView = flag;
				_captured = StaticStage.None;
			}
			if (!flag)
			{
				SelectLiveWindow(eyePoint);
			}
			bool flag2 = IsLinked();
			float num = Vector3.Distance(eyePoint, ((Component)this).transform.position);
			if (!flag2 || num > 12f)
			{
				SetDiscVisible(visible: false);
				if (!flag2)
				{
					_hasFrame = false;
				}
				ResetStaticCapture();
				return;
			}
			EnsureDiscs();
			if (_discsRipple != flag)
			{
				_discsRipple = flag;
				SetDiscMesh(flag ? RippleMesh() : DiscMesh());
			}
			Transform val = ModelOf(_portal);
			bool flag3 = Vector3.Dot(val.forward, ((Component)main).transform.position - val.position) >= 0f;
			ZDO val2 = Portals.ZdoOf(_portal);
			_viewerInFront = ((val2 != null && Portals.IsStonePortal(val2)) ? flag3 : (!flag3));
			if (flag)
			{
				UpdateStaticView(main, val2);
				return;
			}
			if ((Object)(object)_live != (Object)(object)this)
			{
				SetDiscVisible(_hasFrame);
				return;
			}
			TeleportWorld val3 = FindFarPortal(val2);
			if ((Object)(object)val3 == (Object)null)
			{
				SetDiscVisible(_hasFrame);
				return;
			}
			SetDiscVisible(visible: true);
			if (!_hasFrame || !(Time.time < _nextRenderTime))
			{
				_nextRenderTime = Time.time + ((num <= 4f) ? 0f : ((num <= 8f) ? 0.1f : (1f / 3f)));
				Render(main, eyePoint, val, val3);
			}
		}

		private static void SelectLiveWindow(Vector3 eye)
		{
			//IL_0038: 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)
			if (_liveFrame == Time.frameCount)
			{
				return;
			}
			_liveFrame = Time.frameCount;
			_live = null;
			float num = 12f;
			foreach (PortalWindow window in Windows)
			{
				float num2 = Vector3.Distance(eye, ((Component)window).transform.position);
				if (num2 <= num && window.IsLinked())
				{
					num = num2;
					_live = window;
				}
			}
		}

		private bool IsLinked()
		{
			if (_portal.HaveTarget())
			{
				return _portal.TargetFound();
			}
			return false;
		}

		private static TeleportWorld? FindFarPortal(ZDO? zdo)
		{
			return InstanceOf((zdo != null) ? Portals.FarEnd(zdo) : null);
		}

		private static TeleportWorld? InstanceOf(ZDO? farEnd)
		{
			ZNetView val = ((farEnd != null && (Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.FindInstance(farEnd) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).GetComponent<TeleportWorld>();
		}

		private void UpdateStaticView(Camera main, ZDO? zdo)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			ZDO val = ((zdo != null) ? Portals.FarEnd(zdo) : null);
			if (val != null && val.m_uid != _frameFarEnd)
			{
				_hasFrame = false;
				_frameFarEnd = val.m_uid;
				ResetStaticCapture();
			}
			SetDiscVisible(_hasFrame);
			if (_hasFrame)
			{
				AnimateRipple();
			}
			if (_approachedAt < 0f)
			{
				_approachedAt = Time.time;
			}
			if (_captured == StaticStage.Full || val == null || Time.time < _nextStaticCheck || ((Character)Player.m_localPlayer).IsTeleporting())
			{
				return;
			}
			_nextStaticCheck = Time.time + 0.2f;
			TeleportWorld val2 = InstanceOf(val);
			if ((Object)(object)val2 != (Object)null && _farFoundAt < 0f)
			{
				_farFoundAt = Time.time;
			}
			StaticStage staticStage = (((Object)(object)val2 != (Object)null) ? BuiltStage(val, val2) : StaticStage.None);
			if (staticStage <= _captured)
			{
				_readySince = -1f;
				return;
			}
			if (_readySince < 0f)
			{
				_readySince = Time.time;
			}
			if (!(Time.time - _readySince < 0.2f) && _captureFrame != Time.frameCount)
			{
				_captureFrame = Time.frameCount;
				CaptureStatic(main, val2);
				_captured = staticStage;
				_readySince = -1f;
				SetDiscVisible(visible: true);
				if (PerfStats.Enabled)
				{
					OttoBifrostPlugin.Log.LogInfo((object)(string.Format("Static picture of {0} ({1}) ", val.m_uid, (staticStage == StaticStage.Full) ? "whole arrival area" : "near objects") + $"after {Time.time - _approachedAt:F2} s in range: far portal after {SinceApproach(_farFoundAt)}, " + "near zones after " + SinceApproach(_nearZonesAt) + ", near objects after " + SinceApproach(_nearBuiltAt) + " (last waited for " + (_lastBlocker ?? "nothing") + "), " + $"server reports complete {DestinationSync.IsDestinationComplete(val.m_uid)}, " + $"{_settleCount} objects known around the arrival point"));
				}
			}
		}

		private string SinceApproach(float at)
		{
			if (!(at < 0f))
			{
				return $"{at - _approachedAt:F2} s";
			}
			return "not yet";
		}

		private StaticStage BuiltStage(ZDO farEnd, TeleportWorld farPortal)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_011b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ZoneSystem.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || ZDOMan.instance == null)
			{
				return StaticStage.None;
			}
			Transform transform = ((Component)farPortal).transform;
			Vector3 val = transform.position + transform.forward * farPortal.m_exitDistance + Vector3.up;
			int num = DestinationSync.CountKnownObjects(val);
			if (num != _settleCount)
			{
				_settleCount = num;
				_settleChangedAt = Time.time;
			}
			ZoneLoadPatches.NearState nearState = ZoneLoadPatches.NearState.Built;
			if (_captured < StaticStage.Near)
			{
				nearState = ZoneLoadPatches.GetNearState(transform.position, transform.forward, 2f, out ZDO blocker);
				if (blocker != null && PerfStats.Enabled)
				{
					_lastBlocker = ZoneLoadPatches.Describe(blocker, transform.position);
				}
			}
			if (nearState != ZoneLoadPatches.NearState.ZonesMissing && _nearZonesAt < 0f)
			{
				_nearZonesAt = Time.time;
			}
			if (nearState == ZoneLoadPatches.NearState.Built && _nearBuiltAt < 0f)
			{
				_nearBuiltAt = Time.time;
			}
			if (!DestinationSync.IsDestinationComplete(farEnd.m_uid) && !(Time.time - _settleChangedAt >= 1f))
			{
				return StaticStage.None;
			}
			if (ZNetScene.instance.IsAreaReady(val))
			{
				return StaticStage.Full;
			}
			if (_captured >= StaticStage.Near || nearState != ZoneLoadPatches.NearState.Built)
			{
				return StaticStage.None;
			}
			return StaticStage.Near;
		}

		private void ResetStaticCapture()
		{
			_captured = StaticStage.None;
			_settleCount = -1;
			_readySince = -1f;
			_approachedAt = -1f;
			_farFoundAt = -1f;
			_nearZonesAt = -1f;
			_nearBuiltAt = -1f;
			_lastBlocker = null;
		}

		private void CaptureStatic(Camera main, TeleportWorld farPortal)
		{
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_006c: 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)
			Transform transform = ((Component)farPortal).transform;
			Vector3 val = transform.position + Vector3.up * 1.8f;
			Vector3 position = val - transform.forward * 1.5f;
			Quaternion rotation = Quaternion.LookRotation(transform.forward, Vector3.up) * Quaternion.Euler(8f, 0f, 0f);
			_hiddenPortal = null;
			RenderFrom(main, val, position, rotation, farPortal);
		}

		private void Render(Camera main, Vector3 eye, Transform here, TeleportWorld farPortal)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			Matrix4x4 val = Matrix4x4.Rotate(_viewerInFront ? HalfTurn : Quaternion.identity);
			Matrix4x4 val2 = ModelOf(farPortal).localToWorldMatrix * val * here.worldToLocalMatrix;
			Vector3 farEye = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(eye);
			Vector3 position = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(((Component)main).transform.position);
			Vector3 val3 = ((Matrix4x4)(ref val2)).MultiplyVector(((Component)main).transform.forward);
			Vector3 val4 = ((Matrix4x4)(ref val2)).MultiplyVector(((Component)main).transform.up);
			RenderFrom(main, farEye, position, Quaternion.LookRotation(val3, val4), farPortal);
		}

		private void RenderFrom(Camera main, Vector3 farEye, Vector3 position, Quaternion rotation, TeleportWorld farPortal)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			Camera val = EnsureCamera(main);
			float nearClipPlane = 0.5f;
			Vector3 val2 = position - farEye;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			RaycastHit val3 = default(RaycastHit);
			if (magnitude > 0.01f && Physics.SphereCast(farEye, 0.35f, val2 / magnitude, ref val3, magnitude, _blockMask))
			{
				position = farEye + val2 / magnitude * Mathf.Max(((RaycastHit)(ref val3)).distance - 0.1f, 0f);
				nearClipPlane = 0.1f;
			}
			float num = Floating.GetLiquidLevel(position, 1f, (LiquidType)10) + 0.3f;
			if (position.y < num)
			{
				position.y = num;
			}
			((Component)val).transform.SetPositionAndRotation(position, rotation);
			val.fieldOfView = main.fieldOfView;
			val.nearClipPlane = nearClipPlane;
			val.farClipPlane = Mathf.Min(main.farClipPlane, 300f);
			HideFarPortal(farPortal);
			long start = PerfStats.Begin();
			float shadowDistance = QualitySettings.shadowDistance;
			QualitySettings.shadowDistance = 0f;
			try
			{
				val.Render();
			}
			finally
			{
				QualitySettings.shadowDistance = shadowDistance;
				RestoreFarPortal();
			}
			PerfStats.AddPreviewRender(start);
			_hasFrame = true;
		}

		private void HideFarPortal(TeleportWorld farPortal)
		{
			if ((Object)(object)_hiddenPortal != (Object)(object)farPortal)
			{
				_hiddenPortal = farPortal;
				_hiddenRenderers = ((Component)farPortal).GetComponentsInChildren<Renderer>();
				_hiddenWasEnabled = new bool[_hiddenRenderers.Length];
			}
			for (int i = 0; i < _hiddenRenderers.Length; i++)
			{
				Renderer val = _hiddenRenderers[i];
				_hiddenWasEnabled[i] = (Object)(object)val != (Object)null && val.enabled;
				if (_hiddenWasEnabled[i])
				{
					val.enabled = false;
				}
			}
		}

		private void RestoreFarPortal()
		{
			for (int i = 0; i < _hiddenRenderers.Length; i++)
			{
				if (_hiddenWasEnabled[i])
				{
					_hiddenRenderers[i].enabled = true;
				}
			}
		}

		private void SetDiscVisible(bool visible)
		{
			if (!((Object)(object)_frontDisc == (Object)null) && !((Object)(object)_backDisc == (Object)null))
			{
				((Renderer)_frontDisc).enabled = visible && _viewerInFront;
				((Renderer)_backDisc).enabled = visible && !_viewerInFront;
			}
		}

		private void SetDiscMesh(Mesh mesh)
		{
			if (!((Object)(object)_frontDisc == (Object)null) && !((Object)(object)_backDisc == (Object)null))
			{
				((Component)_frontDisc).GetComponent<MeshFilter>().sharedMesh = mesh;
				((Component)_backDisc).GetComponent<MeshFilter>().sharedMesh = mesh;
			}
		}

		private void EnsureDiscs()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_00a4: 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_00da: 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)
			if (!((Object)(object)_frontDisc != (Object)null))
			{
				if (_blockMask == 0)
				{
					_blockMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "terrain", "piece", "piece_nonsolid" });
				}
				_texture = new RenderTexture(512, 512, 24, (RenderTextureFormat)0)
				{
					antiAliasing = 1,
					filterMode = (FilterMode)1
				};
				_material = new Material(Shader.Find("Sprites/Default"))
				{
					mainTexture = (Texture)(object)_texture
				};
				Transform parent = ModelOf(_portal);
				_frontDisc = AddDisc(parent, DiscOffset, Quaternion.identity);
				_backDisc = AddDisc(parent, new Vector3(DiscOffset.x, DiscOffset.y, 0f - DiscOffset.z), HalfTurn);
			}
		}

		private MeshRenderer AddDisc(Transform parent, Vector3 localPosition, Quaternion localRotation)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("OttoBifrostWindow");
			val.transform.SetParent(parent, false);
			val.transform.localPosition = localPosition;
			val.transform.localRotation = localRotation;
			val.transform.localScale = Vector3.one * 2.85f;
			val.AddComponent<MeshFilter>().sharedMesh = DiscMesh();
			MeshRenderer obj = val.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterial = _material;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			((Renderer)obj).enabled = false;
			return obj;
		}

		private Camera EnsureCamera(Camera main)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_camera != (Object)null)
			{
				return _camera;
			}
			_camera = new GameObject("OttoBifrostCamera").AddComponent<Camera>();
			_camera.CopyFrom(main);
			((Behaviour)_camera).enabled = false;
			_camera.targetTexture = _texture;
			_camera.useOcclusionCulling = false;
			_camera.allowMSAA = false;
			_camera.clearFlags = (CameraClearFlags)1;
			_camera.depthTextureMode = (DepthTextureMode)1;
			return _camera;
		}

		private static Transform ModelOf(TeleportWorld portal)
		{
			if (!((Object)(object)portal.m_model != (Object)null))
			{
				return ((Component)portal).transform;
			}
			return ((Component)portal.m_model).transform;
		}

		private static Mesh DiscMesh()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_007a: 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_00