Decompiled source of RossPortals v0.2.5

plugins/RossPortals.Core.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RossPortals.Core")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+480bcd6cb67c3266f0fa61828561de272bc5b8f3")]
[assembly: AssemblyProduct("RossPortals.Core")]
[assembly: AssemblyTitle("RossPortals.Core")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RossPortals.Core
{
	public enum RowKind
	{
		Group,
		Portal
	}
	public readonly struct DisplayRow
	{
		public RowKind Kind { get; }

		public int Depth { get; }

		public string Label { get; }

		public string GroupPath { get; }

		public bool Collapsed { get; }

		public int PortalCount { get; }

		public string PortalId { get; }

		public float Distance { get; }

		private DisplayRow(RowKind kind, int depth, string label, string groupPath, bool collapsed, int portalCount, string portalId, float distance)
		{
			Kind = kind;
			Depth = depth;
			Label = label;
			GroupPath = groupPath;
			Collapsed = collapsed;
			PortalCount = portalCount;
			PortalId = portalId;
			Distance = distance;
		}

		public static DisplayRow Group(int depth, string label, string path, bool collapsed, int portalCount)
		{
			return new DisplayRow(RowKind.Group, depth, label, path, collapsed, portalCount, null, 0f);
		}

		public static DisplayRow Portal(int depth, string label, string portalId, float distance)
		{
			return new DisplayRow(RowKind.Portal, depth, label, null, collapsed: false, 0, portalId, distance);
		}
	}
	public readonly struct PortalEntry
	{
		public string Id { get; }

		public string Name { get; }

		public Vec3 Position { get; }

		public string TargetId { get; }

		public bool HasTarget => !string.IsNullOrEmpty(TargetId);

		public PortalEntry(string id, string name, Vec3 position, string targetId = null)
		{
			Id = id;
			Name = name ?? string.Empty;
			Position = position;
			TargetId = targetId;
		}
	}
	public static class PortalListView
	{
		private sealed class Node
		{
			public string Segment { get; }

			public string Path { get; }

			public Dictionary<string, Node> Children { get; } = new Dictionary<string, Node>(StringComparer.OrdinalIgnoreCase);

			public List<PortalEntry> Leaves { get; } = new List<PortalEntry>();

			public Node(string segment, string path)
			{
				Segment = segment;
				Path = path;
			}

			public Node Child(string segment, char separator)
			{
				if (!Children.TryGetValue(segment, out var value))
				{
					string path = ((Path == null) ? segment : (Path + separator + segment));
					value = new Node(segment, path);
					Children[segment] = value;
				}
				return value;
			}

			public int CountLeaves()
			{
				int num = Leaves.Count;
				foreach (Node value in Children.Values)
				{
					num += value.CountLeaves();
				}
				return num;
			}
		}

		public static IReadOnlyList<DisplayRow> Build(IEnumerable<PortalEntry> portals, char separator, string query, SortMode sort, Vec3 playerPosition, IReadOnlyList<string> recentIds = null, IReadOnlyCollection<string> collapsedGroups = null)
		{
			if (portals == null)
			{
				throw new ArgumentNullException("portals");
			}
			HashSet<string> collapsed = new HashSet<string>((IEnumerable<string>)(((object)collapsedGroups) ?? ((object)Array.Empty<string>())), StringComparer.Ordinal);
			Dictionary<string, int> recentIndex = BuildRecentIndex(recentIds ?? Array.Empty<string>());
			string value = query?.Trim();
			bool flag = !string.IsNullOrEmpty(value);
			List<PortalEntry> list = new List<PortalEntry>();
			foreach (PortalEntry portal in portals)
			{
				if (portal.Id != null && (!flag || portal.Name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0))
				{
					list.Add(portal);
				}
			}
			List<DisplayRow> list2 = new List<DisplayRow>();
			if (sort != SortMode.Name)
			{
				foreach (PortalEntry item in SortLeaves(list, separator, sort, playerPosition, recentIndex))
				{
					list2.Add(DisplayRow.Portal(0, FlatLabel(item), item.Id, item.Position.DistanceTo(playerPosition)));
				}
				return list2;
			}
			Node node = new Node(null, null);
			foreach (PortalEntry item2 in list)
			{
				Insert(node, item2, separator);
			}
			Emit(node, 0, list2, separator, sort, playerPosition, recentIndex, collapsed);
			return list2;
		}

		private static Dictionary<string, int> BuildRecentIndex(IReadOnlyList<string> recent)
		{
			Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal);
			for (int i = 0; i < recent.Count; i++)
			{
				if (recent[i] != null && !dictionary.ContainsKey(recent[i]))
				{
					dictionary[recent[i]] = i;
				}
			}
			return dictionary;
		}

		private static string FlatLabel(PortalEntry portal)
		{
			return portal.Name ?? string.Empty;
		}

		private static void Insert(Node root, PortalEntry portal, char separator)
		{
			IReadOnlyList<string> readOnlyList = PortalName.GroupPath(portal.Name, separator);
			Node node = root;
			foreach (string item in readOnlyList)
			{
				node = node.Child(item, separator);
			}
			node.Leaves.Add(portal);
		}

		private static void Emit(Node node, int depth, List<DisplayRow> rows, char separator, SortMode sort, Vec3 player, Dictionary<string, int> recentIndex, HashSet<string> collapsed)
		{
			foreach (Node item in node.Children.Values.OrderBy<Node, string>((Node c) => c.Segment, StringComparer.OrdinalIgnoreCase))
			{
				bool flag = collapsed.Contains(item.Path);
				rows.Add(DisplayRow.Group(depth, item.Segment, item.Path, flag, item.CountLeaves()));
				if (!flag)
				{
					Emit(item, depth + 1, rows, separator, sort, player, recentIndex, collapsed);
				}
			}
			foreach (PortalEntry item2 in SortLeaves(node.Leaves, separator, sort, player, recentIndex))
			{
				rows.Add(DisplayRow.Portal(depth, PortalName.Leaf(item2.Name, separator), item2.Id, item2.Position.DistanceTo(player)));
			}
		}

		private static IEnumerable<PortalEntry> SortLeaves(List<PortalEntry> leaves, char separator, SortMode sort, Vec3 player, Dictionary<string, int> recentIndex)
		{
			int value;
			return sort switch
			{
				SortMode.Nearest => leaves.OrderBy((PortalEntry p) => p.Position.DistanceTo(player)).ThenBy<PortalEntry, string>(Label, StringComparer.OrdinalIgnoreCase).ThenBy<PortalEntry, string>((PortalEntry p) => p.Id, StringComparer.Ordinal), 
				SortMode.Recent => leaves.OrderBy((PortalEntry p) => (!recentIndex.TryGetValue(p.Id, out value)) ? int.MaxValue : value).ThenBy<PortalEntry, string>(Label, StringComparer.OrdinalIgnoreCase).ThenBy<PortalEntry, string>((PortalEntry p) => p.Id, StringComparer.Ordinal), 
				_ => leaves.OrderBy<PortalEntry, string>(Label, StringComparer.OrdinalIgnoreCase).ThenBy<PortalEntry, string>((PortalEntry p) => p.Id, StringComparer.Ordinal), 
			};
			string Label(PortalEntry p)
			{
				return PortalName.Leaf(p.Name, separator);
			}
		}
	}
	public static class PortalName
	{
		public const char DefaultSeparator = '/';

		public static IReadOnlyList<string> Segments(string name, char separator)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return Array.Empty<string>();
			}
			string[] array = name.Split(separator);
			List<string> list = new List<string>(array.Length);
			string[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				string text = array2[i].Trim();
				if (text.Length > 0)
				{
					list.Add(text);
				}
			}
			return list;
		}

		public static string Leaf(string name, char separator)
		{
			IReadOnlyList<string> readOnlyList = Segments(name, separator);
			if (readOnlyList.Count != 0)
			{
				return readOnlyList[readOnlyList.Count - 1];
			}
			return string.Empty;
		}

		public static IReadOnlyList<string> GroupPath(string name, char separator)
		{
			IReadOnlyList<string> readOnlyList = Segments(name, separator);
			if (readOnlyList.Count <= 1)
			{
				return Array.Empty<string>();
			}
			List<string> list = new List<string>(readOnlyList.Count - 1);
			for (int i = 0; i < readOnlyList.Count - 1; i++)
			{
				list.Add(readOnlyList[i]);
			}
			return list;
		}
	}
	public enum SortMode
	{
		Name,
		Nearest,
		Recent
	}
	public readonly struct Vec3
	{
		public float X { get; }

		public float Y { get; }

		public float Z { get; }

		public Vec3(float x, float y, float z)
		{
			X = x;
			Y = y;
			Z = z;
		}

		public float DistanceTo(Vec3 other)
		{
			float num = X - other.X;
			float num2 = Y - other.Y;
			float num3 = Z - other.Z;
			return (float)Math.Sqrt(num * num + num2 * num2 + num3 * num3);
		}
	}
}

plugins/RossPortals.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using RossPortals.Core;
using RossPortals.Game.Framework;
using RossPortals.Game.Portals;
using RossPortals.Game.UI;
using Splatform;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RossPortals")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+480bcd6cb67c3266f0fa61828561de272bc5b8f3")]
[assembly: AssemblyProduct("RossPortals")]
[assembly: AssemblyTitle("RossPortals")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RossPortals.Game
{
	internal static class ModInfo
	{
		public const string Guid = "com.rossdwest.rossportals";

		public const string Name = "RossPortals";

		public const string Version = "0.2.5";

		public const string XPortalGuid = "yay.spikehimself.xportal";

		public const string KeyTarget = "RossPortals_TargetId";

		public const string KeyPrevious = "RossPortals_PreviousId";

		public const string LegacyKeyTarget = "XPortal_TargetId";

		public const string LegacyKeyPrevious = "XPortal_PreviousId";

		public const string KeyDefault = "RossPortals_Default";

		public const string KeyShowOnMap = "RossPortals_ShowOnMap";

		public const string RpcResync = "RossPortals_Resync";

		public const string RpcSyncPortal = "RossPortals_SyncPortal";

		public const string RpcSyncRequest = "RossPortals_SyncRequest";

		public const string RpcAddOrUpdate = "RossPortals_AddOrUpdate";

		public const string RpcRemove = "RossPortals_Remove";
	}
	[BepInPlugin("com.rossdwest.rossportals", "RossPortals", "0.2.5")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInIncompatibility("yay.spikehimself.xportal")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class RossPortalsPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			_harmony = new Harmony("com.rossdwest.rossportals");
			ValheimCompat.Verify();
			PatchEachClassIndividually();
			PortalConfig.Bind(((BaseUnityPlugin)this).Config);
			GameObject val = new GameObject("RossPortalsManager");
			Object.DontDestroyOnLoad((Object)val);
			val.transform.SetParent(((Component)this).gameObject.transform);
			val.AddComponent<Scheduler>();
			if (!GUIManager.IsHeadless())
			{
				new PortalConfigPanel();
			}
			MinimapManager.OnVanillaMapDataLoaded += PortalManager.RequestInitialSync;
			Log.LogInfo((object)"RossPortals 0.2.5 loaded");
		}

		private void Update()
		{
			if (!Env.IsHeadless)
			{
				PortalConfigPanel.Instance?.HandleInput();
			}
		}

		private void OnDestroy()
		{
			MinimapManager.OnVanillaMapDataLoaded -= PortalManager.RequestInitialSync;
			PortalConfigPanel.Instance?.Dispose();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void PatchEachClassIndividually()
		{
			List<string> list = new List<string>();
			try
			{
				Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly());
				foreach (Type type in typesFromAssembly)
				{
					if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length == 0)
					{
						continue;
					}
					try
					{
						List<MethodInfo> list2 = _harmony.CreateClassProcessor(type).Patch();
						if (list2 == null || list2.Count == 0)
						{
							list.Add(type.Name + "=SKIPPED(Prepare() false or no target)");
							continue;
						}
						foreach (MethodInfo item in list2)
						{
							list.Add(item.DeclaringType?.Name + "." + item.Name + "=OK(via " + type.Name + ")");
						}
					}
					catch (Exception ex)
					{
						list.Add(type.Name + "=FAILED(" + ex.GetType().Name + ")");
						Log.LogError((object)$"Harmony patch '{type.FullName}' failed to apply; continuing without it: {ex}");
					}
				}
			}
			catch (Exception ex2)
			{
				list.Add("enumeration=FAILED(" + ex2.GetType().Name + ")");
				Log.LogError((object)$"Harmony patching failed unexpectedly; continuing without the affected patch(es): {ex2}");
			}
			Log.LogInfo((object)("RossPortals Harmony patches: " + string.Join("; ", list)));
		}
	}
}
namespace RossPortals.Game.UI
{
	internal sealed class PortalConfigPanel
	{
		private readonly struct SelectableRow
		{
			public readonly Button Button;

			public readonly Text Label;

			public readonly string Key;

			public SelectableRow(Button button, Text label, string key)
			{
				Button = button;
				Label = label;
				Key = key;
			}
		}

		private const float PanelWidth = 640f;

		private const float PanelHeight = 600f;

		private const float RowHeight = 30f;

		private GameObject _panel;

		private InputField _nameField;

		private InputField _searchField;

		private Text _destinationText;

		private Toggle _defaultToggle;

		private Toggle _showMapToggle;

		private RectTransform _content;

		private Font _font;

		private readonly Dictionary<SortMode, Text> _sortLabels = new Dictionary<SortMode, Text>();

		private bool _built;

		private PortalRecord _portal;

		private string _selectedKey;

		private SortMode _sort;

		private readonly HashSet<string> _collapsed = new HashSet<string>();

		private List<DisplayRow> _lastRows;

		private readonly List<SelectableRow> _selectableRows = new List<SelectableRow>();

		public static PortalConfigPanel Instance { get; private set; }

		public bool IsOpen
		{
			get
			{
				if ((Object)(object)_panel != (Object)null)
				{
					return _panel.activeSelf;
				}
				return false;
			}
		}

		public PortalConfigPanel()
		{
			Instance = this;
			GUIManager.OnCustomGUIAvailable += OnGuiRecreated;
		}

		private void OnGuiRecreated()
		{
			_built = false;
			_panel = null;
			_portal = null;
			_sortLabels.Clear();
			_selectableRows.Clear();
			_lastRows = null;
		}

		public void Open(PortalRecord portal)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (!Env.IsHeadless && EnsureBuilt())
			{
				PortalManager.RefreshList();
				_portal = portal;
				_selectedKey = (portal.HasTarget ? PortalKey.Of(portal.Target) : null);
				_nameField.text = portal.Name ?? string.Empty;
				_searchField.text = string.Empty;
				_defaultToggle.isOn = portal.IsDefault;
				_showMapToggle.isOn = portal.ShowOnMap;
				_panel.SetActive(true);
				GUIManager.BlockInput(true);
				_lastRows = null;
				Rebuild();
				Scheduler.Instance?.NextFrame(delegate
				{
					_searchField.ActivateInputField();
				});
			}
		}

		public void Close()
		{
			if ((Object)(object)_panel != (Object)null)
			{
				_panel.SetActive(false);
			}
			GUIManager.BlockInput(false);
			_portal = null;
		}

		public void HandleInput()
		{
			if (IsOpen && Input.GetKeyDown((KeyCode)27))
			{
				Close();
			}
		}

		public void OnRegistryChanged()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (IsOpen && _portal != null)
			{
				_portal = PortalRegistry.Instance.GetById(_portal.Id) ?? _portal;
				Rebuild();
			}
		}

		public void Dispose()
		{
			GUIManager.OnCustomGUIAvailable -= OnGuiRecreated;
			if ((Object)(object)_panel != (Object)null)
			{
				Object.Destroy((Object)(object)_panel);
			}
			_panel = null;
			_built = false;
			if (Instance == this)
			{
				Instance = null;
			}
		}

		private bool EnsureBuilt()
		{
			//IL_00a0: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Expected O, but got Unknown
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Expected O, but got Unknown
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Expected O, but got Unknown
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Expected O, but got Unknown
			if (_built && (Object)(object)_panel != (Object)null)
			{
				return true;
			}
			if (GUIManager.Instance == null || (Object)(object)GUIManager.CustomGUIFront == (Object)null)
			{
				RossPortalsPlugin.Log.LogWarning((object)"GUI not ready; cannot open the portal panel yet.");
				return false;
			}
			_built = false;
			_sortLabels.Clear();
			_selectableRows.Clear();
			Font val = (_font = GUIManager.Instance.AveriaSerifBold);
			Transform transform = GUIManager.CustomGUIFront.transform;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 1f);
			_panel = GUIManager.Instance.CreateWoodpanel(transform, val2, val2, Vector2.zero, 640f, 600f, false);
			_panel.SetActive(false);
			GUIManager.Instance.CreateText("Configure Portal", _panel.transform, val3, val3, new Vector2(0f, -28f), val, 24, Color.white, true, Color.black, 600f, 34f, false);
			_nameField = GUIManager.Instance.CreateInputField(_panel.transform, val3, val3, new Vector2(0f, -74f), (ContentType)0, "Portal name", 18, 580f, 36f).GetComponent<InputField>();
			_searchField = GUIManager.Instance.CreateInputField(_panel.transform, val3, val3, new Vector2(0f, -118f), (ContentType)0, "Search portals...", 18, 580f, 34f).GetComponent<InputField>();
			((UnityEvent<string>)(object)_searchField.onValueChanged).AddListener((UnityAction<string>)delegate
			{
				Rebuild();
			});
			CreateSortButton((SortMode)0, "Name", -160f, val);
			CreateSortButton((SortMode)1, "Nearest", 0f, val);
			CreateSortButton((SortMode)2, "Recent", 160f, val);
			_destinationText = GUIManager.Instance.CreateText(string.Empty, _panel.transform, val3, val3, new Vector2(-110f, -198f), val, 18, Color.white, true, Color.black, 360f, 30f, false).GetComponent<Text>();
			_destinationText.alignment = (TextAnchor)3;
			((UnityEvent)GUIManager.Instance.CreateButton("Clear", _panel.transform, val3, val3, new Vector2(210f, -198f), 110f, 30f).GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				Select(null);
			});
			GameObject obj = GUIManager.Instance.CreateScrollView(_panel.transform, false, true, 12f, 6f, HandleColors(), new Color(0f, 0f, 0f, 0.6f), 590f, 300f);
			((RectTransform)obj.transform).anchoredPosition = new Vector2(0f, -85f);
			ScrollRect componentInChildren = obj.GetComponentInChildren<ScrollRect>();
			_content = componentInChildren.content;
			componentInChildren.scrollSensitivity = 400f;
			VerticalLayoutGroup component = ((Component)_content).GetComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)component).spacing = 2f;
			((LayoutGroup)component).padding = new RectOffset(6, 6, 6, 6);
			((UnityEvent)GUIManager.Instance.CreateButton("OK", _panel.transform, val3, val3, new Vector2(225f, -566f), 130f, 40f).GetComponent<Button>().onClick).AddListener(new UnityAction(Submit));
			((UnityEvent)GUIManager.Instance.CreateButton("Cancel", _panel.transform, val3, val3, new Vector2(81f, -566f), 130f, 40f).GetComponent<Button>().onClick).AddListener(new UnityAction(Close));
			_defaultToggle = CreateCheckbox("Default", -278f, -566f, 70f);
			_showMapToggle = CreateCheckbox("Show on map", -150f, -566f, 130f);
			_built = true;
			return true;
		}

		private Toggle CreateCheckbox(string label, float x, float y, float labelWidth)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_009f: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 1f);
			GameObject val2 = GUIManager.Instance.CreateToggle(_panel.transform, 24f, 24f);
			RectTransform val3 = (RectTransform)val2.transform;
			val3.anchorMin = val;
			val3.anchorMax = val;
			val3.pivot = new Vector2(0.5f, 0.5f);
			val3.anchoredPosition = new Vector2(x, y);
			Text[] componentsInChildren = val2.GetComponentsInChildren<Text>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].text = string.Empty;
			}
			Text component = GUIManager.Instance.CreateText(label, _panel.transform, val, val, new Vector2(x + 18f + labelWidth / 2f, y), _font, 16, Color.white, true, Color.black, labelWidth, 24f, false).GetComponent<Text>();
			component.alignment = (TextAnchor)3;
			((Graphic)component).raycastTarget = false;
			return val2.GetComponent<Toggle>();
		}

		private void CreateSortButton(SortMode mode, string token, float x, Font font)
		{
			//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_002f: 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)
			//IL_0049: 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_007a: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GUIManager.Instance.CreateButton(token, _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(x, -156f), 150f, 30f);
			((UnityEvent)val.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				_sort = mode;
				Rebuild();
			});
			_sortLabels[mode] = val.GetComponentInChildren<Text>();
		}

		private static ColorBlock HandleColors()
		{
			//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_001c: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			ColorBlock defaultColorBlock = ColorBlock.defaultColorBlock;
			((ColorBlock)(ref defaultColorBlock)).normalColor = new Color(0.35f, 0.35f, 0.35f, 1f);
			((ColorBlock)(ref defaultColorBlock)).highlightedColor = new Color(0.5f, 0.5f, 0.5f, 1f);
			((ColorBlock)(ref defaultColorBlock)).pressedColor = new Color(0.6f, 0.6f, 0.6f, 1f);
			((ColorBlock)(ref defaultColorBlock)).colorMultiplier = 1f;
			return defaultColorBlock;
		}

		private void Rebuild()
		{
			//IL_002f: 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_0034: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Expected O, but got Unknown
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			if (!_built || _portal == null)
			{
				return;
			}
			Vector3 val = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Component)Player.m_localPlayer).transform.position : Vector3.zero);
			IReadOnlyList<DisplayRow> readOnlyList = PortalListView.Build((IEnumerable<PortalEntry>)PortalRegistry.Instance.BuildEntries(_portal.Id), PortalConfig.Separator, _searchField.text, _sort, new Vec3(val.x, val.y, val.z), PortalManager.RecentKeys, (IReadOnlyCollection<string>)_collapsed);
			if (_lastRows != null && ((Transform)_content).childCount > 0 && RowsEqual(_lastRows, readOnlyList))
			{
				return;
			}
			_lastRows = new List<DisplayRow>(readOnlyList);
			for (int num = ((Transform)_content).childCount - 1; num >= 0; num--)
			{
				Object.DestroyImmediate((Object)(object)((Component)((Transform)_content).GetChild(num)).gameObject);
			}
			_selectableRows.Clear();
			_destinationText.text = "Destination: " + SelectedName();
			foreach (KeyValuePair<SortMode, Text> sortLabel in _sortLabels)
			{
				((Graphic)sortLabel.Value).color = ((sortLabel.Key == _sort) ? Color.yellow : Color.white);
			}
			BuildRow("(no destination)", "", 0, isGroup: false, _selectedKey == null, (UnityAction)delegate
			{
				Select(null);
			}, null, selectable: true);
			foreach (DisplayRow item in readOnlyList)
			{
				AddRow(item);
			}
		}

		private static bool RowsEqual(IReadOnlyList<DisplayRow> a, IReadOnlyList<DisplayRow> b)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (a.Count != b.Count)
			{
				return false;
			}
			for (int i = 0; i < a.Count; i++)
			{
				DisplayRow val = a[i];
				DisplayRow val2 = b[i];
				if (((DisplayRow)(ref val)).Kind != ((DisplayRow)(ref val2)).Kind || ((DisplayRow)(ref val)).Depth != ((DisplayRow)(ref val2)).Depth || ((DisplayRow)(ref val)).Label != ((DisplayRow)(ref val2)).Label || ((DisplayRow)(ref val)).GroupPath != ((DisplayRow)(ref val2)).GroupPath || ((DisplayRow)(ref val)).Collapsed != ((DisplayRow)(ref val2)).Collapsed || ((DisplayRow)(ref val)).PortalCount != ((DisplayRow)(ref val2)).PortalCount || ((DisplayRow)(ref val)).PortalId != ((DisplayRow)(ref val2)).PortalId || FormatDistance(((DisplayRow)(ref val)).Distance) != FormatDistance(((DisplayRow)(ref val2)).Distance))
				{
					return false;
				}
			}
			return true;
		}

		private void AddRow(DisplayRow row)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			if ((int)((DisplayRow)(ref row)).Kind == 0)
			{
				string arrow = (((DisplayRow)(ref row)).Collapsed ? "▶" : "▼");
				string path = ((DisplayRow)(ref row)).GroupPath;
				BuildRow(((DisplayRow)(ref row)).Label, ((DisplayRow)(ref row)).PortalCount.ToString(), ((DisplayRow)(ref row)).Depth, isGroup: true, selected: false, (UnityAction)delegate
				{
					if (!_collapsed.Remove(path))
					{
						_collapsed.Add(path);
					}
					Rebuild();
				}, arrow);
			}
			else
			{
				string label = (string.IsNullOrEmpty(((DisplayRow)(ref row)).Label) ? "(no name)" : ((DisplayRow)(ref row)).Label);
				bool selected = ((DisplayRow)(ref row)).PortalId == _selectedKey;
				string key = ((DisplayRow)(ref row)).PortalId;
				BuildRow(label, FormatDistance(((DisplayRow)(ref row)).Distance), ((DisplayRow)(ref row)).Depth, isGroup: false, selected, (UnityAction)delegate
				{
					Select(key);
				}, null, selectable: true, key);
			}
		}

		private void BuildRow(string label, string trailer, int depth, bool isGroup, bool selected, UnityAction onClick, string arrow = null, bool selectable = false, string key = null)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0052: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("row", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val.transform.SetParent((Transform)(object)_content, false);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = Color.white;
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			((Selectable)component2).transition = (Transition)1;
			ColorBlock val2 = (((Selectable)component2).colors = RowColors(isGroup, selected));
			((Behaviour)component2).enabled = false;
			((Behaviour)component2).enabled = true;
			((Graphic)component).canvasRenderer.SetColor(((ColorBlock)(ref val2)).normalColor);
			((UnityEvent)component2.onClick).AddListener(onClick);
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.minHeight = 30f;
			obj.preferredHeight = 30f;
			obj.flexibleWidth = 1f;
			Color color = RowTextColor(isGroup, selected);
			float num = 12f + (float)depth * 22f;
			if (arrow != null)
			{
				AddLabel(val.transform, arrow, (TextAnchor)3, color, num, 60f, 11);
				num += 14f;
			}
			Text label2 = AddLabel(val.transform, label, (TextAnchor)3, color, num, 60f);
			if (!string.IsNullOrEmpty(trailer))
			{
				AddLabel(val.transform, trailer, (TextAnchor)5, new Color(0.65f, 0.65f, 0.62f), 8f, 10f);
			}
			if (selectable)
			{
				_selectableRows.Add(new SelectableRow(component2, label2, key));
			}
		}

		private Text AddLabel(Transform parent, string text, TextAnchor anchor, Color color, float leftPad, float rightPad, int fontSize = 17)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("label", new Type[3]
			{
				typeof(RectTransform),
				typeof(Text),
				typeof(Outline)
			});
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.offsetMin = new Vector2(leftPad, 0f);
			val2.offsetMax = new Vector2(0f - rightPad, 0f);
			Text component = val.GetComponent<Text>();
			component.font = _font;
			component.fontSize = fontSize;
			((Graphic)component).color = color;
			component.alignment = anchor;
			component.horizontalOverflow = (HorizontalWrapMode)1;
			component.verticalOverflow = (VerticalWrapMode)0;
			component.text = text;
			((Shadow)val.GetComponent<Outline>()).effectColor = new Color(0f, 0f, 0f, 0.6f);
			return component;
		}

		private static ColorBlock RowColors(bool isGroup, bool selected)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_005e: 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_009a: 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_00c4: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			Color val = (selected ? new Color(0.85f, 0.7f, 0.2f, 0.3f) : (isGroup ? new Color(1f, 1f, 1f, 0.1f) : new Color(1f, 1f, 1f, 0.02f)));
			ColorBlock defaultColorBlock = ColorBlock.defaultColorBlock;
			((ColorBlock)(ref defaultColorBlock)).normalColor = val;
			((ColorBlock)(ref defaultColorBlock)).highlightedColor = new Color(1f, 1f, 1f, 0.16f);
			((ColorBlock)(ref defaultColorBlock)).pressedColor = new Color(1f, 1f, 1f, 0.24f);
			((ColorBlock)(ref defaultColorBlock)).selectedColor = val;
			((ColorBlock)(ref defaultColorBlock)).colorMultiplier = 1f;
			((ColorBlock)(ref defaultColorBlock)).fadeDuration = 0.08f;
			return defaultColorBlock;
		}

		private void Select(string key)
		{
			//IL_0051: 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)
			_selectedKey = key;
			_destinationText.text = "Destination: " + SelectedName();
			foreach (SelectableRow selectableRow in _selectableRows)
			{
				bool selected = selectableRow.Key == _selectedKey;
				((Selectable)selectableRow.Button).colors = RowColors(isGroup: false, selected);
				((Graphic)selectableRow.Label).color = RowTextColor(isGroup: false, selected);
			}
		}

		private static Color RowTextColor(bool isGroup, bool selected)
		{
			//IL_003f: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			if (!selected)
			{
				if (!isGroup)
				{
					return new Color(0.92f, 0.9f, 0.85f);
				}
				return new Color(0.85f, 0.9f, 1f);
			}
			return new Color(1f, 0.86f, 0.4f);
		}

		private void Submit()
		{
			//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_003a: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			ZDOID newTarget = ZDOID.None;
			if (_selectedKey != null)
			{
				PortalRecord byKey = PortalRegistry.Instance.GetByKey(_selectedKey);
				if (byKey != null)
				{
					newTarget = byKey.Id;
				}
			}
			PortalManager.SubmitPortalConfig(_portal, _nameField.text, newTarget, _defaultToggle.isOn, _showMapToggle.isOn);
			Close();
		}

		private string SelectedName()
		{
			if (_selectedKey == null)
			{
				return "(none)";
			}
			PortalRecord byKey = PortalRegistry.Instance.GetByKey(_selectedKey);
			if (byKey == null)
			{
				return "(none)";
			}
			if (!string.IsNullOrEmpty(byKey.Name))
			{
				return byKey.Name;
			}
			return "(no name)";
		}

		private static string FormatDistance(float metres)
		{
			if (metres >= 1000f)
			{
				return $"{metres / 1000f:0.0} km";
			}
			return $"{(int)metres} m";
		}
	}
}
namespace RossPortals.Game.Portals
{
	internal static class Env
	{
		public static bool IsServer
		{
			get
			{
				if ((Object)(object)ZNet.instance != (Object)null)
				{
					return ZNet.instance.IsServer();
				}
				return false;
			}
		}

		public static bool IsHeadless => GUIManager.IsHeadless();

		public static bool GameStarted { get; set; }

		public static bool ShuttingDown
		{
			get
			{
				if ((Object)(object)Game.instance != (Object)null)
				{
					return Game.instance.m_shuttingDown;
				}
				return false;
			}
		}

		public static long ServerPeerId => ZRoutedRpc.instance.GetServerPeerID();
	}
	internal static class MapPins
	{
		private const PinType PinType = (PinType)6;

		private static readonly Dictionary<string, PinData> _pins = new Dictionary<string, PinData>();

		public static void Refresh()
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			if (Env.IsHeadless || (Object)(object)Minimap.instance == (Object)null)
			{
				return;
			}
			HashSet<string> seen = new HashSet<string>();
			foreach (PortalRecord item in PortalRegistry.Instance.GetList())
			{
				if (!item.ShowOnMap)
				{
					continue;
				}
				string key = item.Key;
				seen.Add(key);
				string text = (string.IsNullOrEmpty(item.Name) ? "Portal" : item.Name);
				if (_pins.TryGetValue(key, out var value))
				{
					if (value.m_pos == item.Location && value.m_name == text)
					{
						continue;
					}
					Minimap.instance.RemovePin(value);
				}
				_pins[key] = Minimap.instance.AddPin(item.Location, (PinType)6, text, false, false, 0L, default(PlatformUserID));
			}
			foreach (string item2 in _pins.Keys.Where((string k) => !seen.Contains(k)).ToList())
			{
				Minimap.instance.RemovePin(_pins[item2]);
				_pins.Remove(item2);
			}
		}

		public static void Clear()
		{
			if ((Object)(object)Minimap.instance != (Object)null)
			{
				foreach (PinData value in _pins.Values)
				{
					Minimap.instance.RemovePin(value);
				}
			}
			_pins.Clear();
		}
	}
	internal static class PortalConfig
	{
		private static ConfigEntry<string> _separator;

		public static char Separator
		{
			get
			{
				string text = _separator?.Value;
				if (!string.IsNullOrEmpty(text))
				{
					return text[0];
				}
				return '/';
			}
		}

		public static void Bind(ConfigFile config)
		{
			_separator = config.Bind<string>("Grouping", "FolderSeparator", "/", "The character in a portal's name that starts a folder. \"Mines/Copper\" puts portal \"Copper\" in folder \"Mines\". Client-side; affects only how your own list is grouped.");
		}
	}
	internal static class PortalKey
	{
		public unsafe static string Of(ZDOID id)
		{
			return ((object)(*(ZDOID*)(&id))/*cast due to .constrained prefix*/).ToString();
		}
	}
	internal static class PortalManager
	{
		private const int RecentCap = 30;

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

		public static IReadOnlyList<string> RecentKeys => _recent;

		public static void OnGameStarted()
		{
			PortalRegistry.Instance.Reset();
			MapPins.Clear();
			PortalRpc.Register();
		}

		public static void RequestInitialSync()
		{
			PlayerProfile val = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile() : null);
			PortalRpc.RequestSync(((val != null) ? val.GetName() : "a player") + " joined");
		}

		public static void RefreshList()
		{
			PortalRpc.RequestSync("panel opened");
		}

		public static void ProcessSyncRequest(string reason)
		{
			List<ZDO> portalList = ZDOMan.instance.GetPortalList();
			PortalRegistry.Instance.ApplyPortalZdos(portalList);
			RossPortalsPlugin.Log.LogInfo((object)$"Portal sync ({reason}): server sees {portalList.Count} portal(s); broadcasting.");
			PortalRpc.BroadcastResync(PortalRegistry.Instance.Pack(), reason);
		}

		public static void ServerAddOrUpdate(PortalRecord record)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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)
			PortalRecord portalRecord = PortalRegistry.Instance.AddOrUpdate(record);
			WriteWithRetry(portalRecord, 5);
			PortalRpc.BroadcastPortal(portalRecord);
			if (portalRecord.IsDefault)
			{
				foreach (PortalRecord item in PortalRegistry.Instance.GetList())
				{
					if (!(item.Id == portalRecord.Id) && item.IsDefault)
					{
						item.IsDefault = false;
						PortalZdo.Write(item);
						PortalRpc.BroadcastPortal(item);
					}
				}
			}
			if (portalRecord.HasTarget)
			{
				PortalRecord byId = PortalRegistry.Instance.GetById(portalRecord.Target);
				if (byId != null && !byId.HasTarget)
				{
					byId.Target = portalRecord.Id;
					ServerAddOrUpdate(byId);
				}
			}
		}

		public static void ServerRemove(ZDOID id)
		{
			//IL_0005: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (!PortalRegistry.Instance.Remove(id))
			{
				return;
			}
			foreach (PortalRecord item in PortalRegistry.Instance.GetPortalsWithTarget(id))
			{
				item.Target = ZDOID.None;
				ServerAddOrUpdate(item);
			}
			PortalRpc.BroadcastResync(PortalRegistry.Instance.Pack(), "portal removed");
		}

		private static void WriteWithRetry(PortalRecord record, int attempts)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (ZDOMan.instance.GetZDO(record.Id) != null)
			{
				PortalZdo.Write(record);
				return;
			}
			if (attempts <= 0 || (Object)(object)Scheduler.Instance == (Object)null)
			{
				RossPortalsPlugin.Log.LogWarning((object)$"Portal ZDO {record.Id} never materialised; name/target not persisted.");
				return;
			}
			Scheduler.Instance.AfterFrames(3, delegate
			{
				WriteWithRetry(record, attempts - 1);
			});
		}

		public static void OnPortalPlaced(ZDOID id, Vector3 location)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//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_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_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_0021: Unknown result type (might be due to invalid IL or missing references)
			ZDOMan.instance.ForceSendZDO(id);
			ZDOID target = ResolveDefaultTarget(id);
			PortalRpc.RequestAddOrUpdate(new PortalRecord(id)
			{
				Location = location,
				Target = target
			});
		}

		public static void OnPortalDestroyed(ZDOID id)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			PortalRpc.RequestRemove(id);
		}

		public static string BuildHoverText(ZDOID id, Vector3 location)
		{
			//IL_0005: 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)
			PortalRecord obj = PortalRegistry.Instance.GetById(id) ?? Adopt(id, location);
			string text = FriendlyName(obj.Name);
			string text2 = FriendlyTarget(obj);
			return Localization.instance.Localize("Name: " + text + "\nDestination: " + text2 + "\n[<color=yellow><b>$KEY_Use</b></color>] Configure");
		}

		public static void OnPortalInteract(ZDOID id)
		{
			//IL_0014: 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_002a: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			if (!Env.IsHeadless && PortalConfigPanel.Instance != null)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(id);
				PortalRecord portal = PortalRegistry.Instance.GetById(id) ?? Adopt(id, (zDO != null) ? zDO.GetPosition() : Vector3.zero);
				PortalConfigPanel.Instance.Open(portal);
			}
		}

		public static void SubmitPortalConfig(PortalRecord portal, string newName, ZDOID newTarget, bool isDefault, bool showOnMap)
		{
			//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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (newName == null)
			{
				newName = string.Empty;
			}
			if (!(portal.Name == newName) || !(portal.Target == newTarget) || portal.IsDefault != isDefault || portal.ShowOnMap != showOnMap)
			{
				portal.Name = newName;
				portal.Target = newTarget;
				portal.IsDefault = isDefault;
				portal.ShowOnMap = showOnMap;
				PortalRpc.RequestAddOrUpdate(portal);
			}
		}

		public static void RecordUsed(ZDOID target)
		{
			//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_000e: Unknown result type (might be due to invalid IL or missing references)
			if (!(target == ZDOID.None))
			{
				string item = PortalKey.Of(target);
				_recent.Remove(item);
				_recent.Insert(0, item);
				if (_recent.Count > 30)
				{
					_recent.RemoveRange(30, _recent.Count - 30);
				}
			}
		}

		public static void NotifyListChanged()
		{
			if (!Env.IsHeadless)
			{
				PortalConfigPanel.Instance?.OnRegistryChanged();
				MapPins.Refresh();
			}
		}

		public static ZDOID ResolveDefaultTarget(ZDOID excludeId)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			foreach (PortalRecord item in PortalRegistry.Instance.GetList())
			{
				if (item.IsDefault && item.Id != excludeId)
				{
					return item.Id;
				}
			}
			return ZDOID.None;
		}

		private static PortalRecord Adopt(ZDOID id, Vector3 location)
		{
			//IL_0005: 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_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_0044: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			ZDO zDO = ZDOMan.instance.GetZDO(id);
			PortalRecord portalRecord = new PortalRecord(id)
			{
				Location = location,
				Name = ((zDO != null) ? (PortalZdo.GetName(zDO) ?? string.Empty) : string.Empty),
				Target = ((zDO != null) ? PortalZdo.GetTarget(zDO) : ZDOID.None)
			};
			PortalRegistry.Instance.AddOrUpdate(portalRecord);
			PortalRpc.RequestSync("adopted an unknown portal");
			return portalRecord;
		}

		private static string FriendlyName(string name)
		{
			if (!string.IsNullOrEmpty(name))
			{
				return name;
			}
			return "(no name)";
		}

		private static string FriendlyTarget(PortalRecord portal)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!portal.HasTarget)
			{
				return "(none)";
			}
			PortalRecord byId = PortalRegistry.Instance.GetById(portal.Target);
			if (byId == null)
			{
				return "(none)";
			}
			return FriendlyName(byId.Name);
		}
	}
	internal sealed class PortalRecord
	{
		public ZDOID Id;

		public string Name;

		public Vector3 Location;

		public ZDOID Target;

		public bool IsDefault;

		public bool ShowOnMap = true;

		public bool HasTarget
		{
			get
			{
				//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)
				if (Target != ZDOID.None)
				{
					return !((ZDOID)(ref Target)).IsNone();
				}
				return false;
			}
		}

		public string Key => PortalKey.Of(Id);

		public PortalRecord(ZDOID id)
		{
			//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_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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			Id = id;
			Name = string.Empty;
			Location = Vector3.zero;
			Target = ZDOID.None;
		}

		public PortalEntry ToCore()
		{
			//IL_002d: 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)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			return new PortalEntry(Key, Name, new Vec3(Location.x, Location.y, Location.z), HasTarget ? PortalKey.Of(Target) : null);
		}

		public ZPackage Pack()
		{
			//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_0007: 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_0026: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write(Id);
			val.Write(Name ?? string.Empty);
			val.Write(Location);
			val.Write(Target);
			val.Write(IsDefault);
			val.Write(ShowOnMap);
			return val;
		}

		public static PortalRecord FromPackage(ZPackage pkg)
		{
			//IL_0001: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			return new PortalRecord(pkg.ReadZDOID())
			{
				Name = pkg.ReadString(),
				Location = pkg.ReadVector3(),
				Target = pkg.ReadZDOID(),
				IsDefault = pkg.ReadBool(),
				ShowOnMap = pkg.ReadBool()
			};
		}
	}
	internal sealed class PortalRegistry
	{
		private readonly Dictionary<ZDOID, PortalRecord> _portals = new Dictionary<ZDOID, PortalRecord>();

		public static PortalRegistry Instance { get; } = new PortalRegistry();

		public int Count => _portals.Count;

		private PortalRegistry()
		{
		}

		public bool Contains(ZDOID id)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return _portals.ContainsKey(id);
		}

		public PortalRecord GetById(ZDOID id)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (!_portals.TryGetValue(id, out var value))
			{
				return null;
			}
			return value;
		}

		public PortalRecord GetByKey(string key)
		{
			if (key != null)
			{
				return _portals.Values.FirstOrDefault((PortalRecord p) => p.Key == key);
			}
			return null;
		}

		public List<PortalRecord> GetList()
		{
			return _portals.Values.ToList();
		}

		public List<PortalRecord> GetPortalsWithTarget(ZDOID target)
		{
			//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)
			return _portals.Values.Where((PortalRecord p) => p.Target == target).ToList();
		}

		public PortalRecord AddOrUpdate(PortalRecord portal)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			_portals[portal.Id] = portal;
			return portal;
		}

		public bool Remove(ZDOID id)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return _portals.Remove(id);
		}

		public void Reset()
		{
			_portals.Clear();
		}

		public IReadOnlyList<PortalEntry> BuildEntries(ZDOID exclude)
		{
			//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_003c: Unknown result type (might be due to invalid IL or missing references)
			List<PortalEntry> list = new List<PortalEntry>(_portals.Count);
			foreach (PortalRecord value in _portals.Values)
			{
				if (!(value.Id == exclude))
				{
					list.Add(value.ToCore());
				}
			}
			return list;
		}

		public ZPackage Pack()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			List<PortalRecord> list = GetList();
			ZPackage val = new ZPackage();
			val.Write(list.Count);
			foreach (PortalRecord item in list)
			{
				val.Write(item.Pack());
			}
			return val;
		}

		public void ApplyResync(ZPackage pkg)
		{
			int num = pkg.ReadInt();
			List<PortalRecord> list = new List<PortalRecord>(num);
			for (int i = 0; i < num; i++)
			{
				list.Add(PortalRecord.FromPackage(pkg.ReadPackage()));
			}
			ReplaceAll(list);
		}

		public void ApplyPortalZdos(IEnumerable<ZDO> zdos)
		{
			ReplaceAll(zdos.Select(PortalZdo.Read).ToList());
		}

		private void ReplaceAll(List<PortalRecord> incoming)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			foreach (PortalRecord item in incoming)
			{
				AddOrUpdate(item);
			}
			HashSet<ZDOID> incomingIds = new HashSet<ZDOID>(incoming.Select((PortalRecord p) => p.Id));
			foreach (ZDOID item2 in _portals.Keys.Where((ZDOID id) => !incomingIds.Contains(id)).ToList())
			{
				_portals.Remove(item2);
			}
		}
	}
	internal static class PortalRpc
	{
		public static void Register()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			instance.Register<string>("RossPortals_SyncRequest", (Action<long, string>)OnSyncRequest);
			instance.Register<ZPackage>("RossPortals_AddOrUpdate", (Action<long, ZPackage>)OnAddOrUpdate);
			instance.Register<ZDOID>("RossPortals_Remove", (Action<long, ZDOID>)OnRemove);
			instance.Register<ZPackage>("RossPortals_SyncPortal", (Action<long, ZPackage>)OnPortalSynced);
			instance.Register<ZPackage, string>("RossPortals_Resync", (Action<long, ZPackage, string>)OnResync);
		}

		public static void RequestSync(string reason)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC(Env.ServerPeerId, "RossPortals_SyncRequest", new object[1] { reason });
		}

		public static void RequestAddOrUpdate(PortalRecord record)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC(Env.ServerPeerId, "RossPortals_AddOrUpdate", new object[1] { record.Pack() });
		}

		public static void RequestRemove(ZDOID id)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			ZRoutedRpc.instance.InvokeRoutedRPC(Env.ServerPeerId, "RossPortals_Remove", new object[1] { id });
		}

		public static void BroadcastPortal(PortalRecord record)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.GetConnectedPeers().Count != 0)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RossPortals_SyncPortal", new object[1] { record.Pack() });
			}
		}

		public static void BroadcastResync(ZPackage pkg, string reason)
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.GetConnectedPeers().Count != 0)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RossPortals_Resync", new object[2] { pkg, reason });
			}
		}

		private static void OnSyncRequest(long sender, string reason)
		{
			if (Env.IsServer)
			{
				PortalManager.ProcessSyncRequest(reason);
			}
		}

		private static void OnAddOrUpdate(long sender, ZPackage pkg)
		{
			if (Env.IsServer)
			{
				PortalManager.ServerAddOrUpdate(PortalRecord.FromPackage(pkg));
			}
		}

		private static void OnRemove(long sender, ZDOID id)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (Env.IsServer)
			{
				PortalManager.ServerRemove(id);
			}
		}

		private static void OnPortalSynced(long sender, ZPackage pkg)
		{
			if (!Env.IsServer)
			{
				PortalRegistry.Instance.AddOrUpdate(PortalRecord.FromPackage(pkg));
				PortalManager.NotifyListChanged();
			}
		}

		private static void OnResync(long sender, ZPackage pkg, string reason)
		{
			if (!Env.IsServer)
			{
				PortalRegistry.Instance.ApplyResync(pkg);
				RossPortalsPlugin.Log.LogInfo((object)$"Portal resync ({reason}): now know {PortalRegistry.Instance.Count} portal(s).");
				PortalManager.NotifyListChanged();
			}
		}
	}
	internal static class PortalZdo
	{
		public static string GetName(ZDO zdo)
		{
			return zdo.GetString(ZDOVars.s_tag, "");
		}

		public static void SetName(ZDO zdo, string name)
		{
			zdo.Set(ZDOVars.s_tag, name ?? string.Empty);
		}

		public static ZDOID GetTarget(ZDO zdo)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//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_000d: 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_001f: 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)
			ZDOID zDOID = zdo.GetZDOID("RossPortals_TargetId");
			if (zDOID == ZDOID.None)
			{
				zDOID = zdo.GetZDOID("XPortal_TargetId");
			}
			return zDOID;
		}

		public static ZDOID GetPrevious(ZDO zdo)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//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_000d: 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_001f: 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)
			ZDOID zDOID = zdo.GetZDOID("RossPortals_PreviousId");
			if (zDOID == ZDOID.None)
			{
				zDOID = zdo.GetZDOID("XPortal_PreviousId");
			}
			return zDOID;
		}

		public static PortalRecord Read(ZDO zdo)
		{
			//IL_0001: 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_0027: 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)
			return new PortalRecord(zdo.m_uid)
			{
				Name = (GetName(zdo) ?? string.Empty),
				Location = zdo.GetPosition(),
				Target = GetTarget(zdo),
				IsDefault = zdo.GetBool("RossPortals_Default", false),
				ShowOnMap = zdo.GetBool("RossPortals_ShowOnMap", true)
			};
		}

		public static void Write(PortalRecord record)
		{
			//IL_0006: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			ZDO zDO = ZDOMan.instance.GetZDO(record.Id);
			if (zDO != null)
			{
				zDO.SetOwner(ZDOMan.GetSessionID());
				SetName(zDO, record.Name);
				zDO.Set("RossPortals_PreviousId", zDO.m_uid);
				zDO.Set("RossPortals_Default", record.IsDefault);
				zDO.Set("RossPortals_ShowOnMap", record.ShowOnMap);
				SetTarget(zDO, record.Target);
			}
		}

		private static void SetTarget(ZDO zdo, ZDOID target)
		{
			//IL_0006: 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)
			zdo.Set("RossPortals_TargetId", target);
			zdo.SetConnection((ConnectionType)1, target);
		}

		public static void RestoreConnections()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_005b: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00de: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			List<ZDO> portalList = ZDOMan.instance.GetPortalList();
			if (portalList == null || portalList.Count == 0)
			{
				return;
			}
			HashSet<ZDOID> hashSet = new HashSet<ZDOID>();
			Dictionary<ZDOID, ZDOID> dictionary = new Dictionary<ZDOID, ZDOID>();
			foreach (ZDO item in portalList)
			{
				hashSet.Add(item.m_uid);
				ZDOID previous = GetPrevious(item);
				if (previous != ZDOID.None)
				{
					dictionary[previous] = item.m_uid;
				}
			}
			foreach (ZDO item2 in portalList)
			{
				ZDOID value = GetTarget(item2);
				if (!(value == ZDOID.None) && (hashSet.Contains(value) || dictionary.TryGetValue(value, out value)))
				{
					item2.SetOwner(ZDOMan.GetSessionID());
					item2.SetConnection((ConnectionType)1, value);
					item2.Set("RossPortals_TargetId", value);
				}
			}
			foreach (ZDO item3 in portalList)
			{
				item3.Set("RossPortals_PreviousId", item3.m_uid);
			}
		}
	}
	internal sealed class Scheduler : MonoBehaviour
	{
		public static Scheduler Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		public void NextFrame(Action action)
		{
			AfterFrames(1, action);
		}

		public void AfterFrames(int frames, Action action)
		{
			if (action != null)
			{
				if (!((Behaviour)this).isActiveAndEnabled)
				{
					action();
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(Run(frames, action));
				}
			}
		}

		private static IEnumerator Run(int frames, Action action)
		{
			for (int i = 0; i < frames; i++)
			{
				yield return null;
			}
			action();
		}
	}
}
namespace RossPortals.Game.Patches
{
	[HarmonyPatch(typeof(Game), "Awake")]
	internal static class Game_Awake
	{
		private static void Prefix(ref bool ___isModded)
		{
			___isModded = true;
		}
	}
	[HarmonyPatch(typeof(Game), "Start")]
	internal static class Game_Start
	{
		private static void Postfix()
		{
			Env.GameStarted = true;
			PortalManager.OnGameStarted();
		}
	}
	[HarmonyPatch(typeof(Game), "ConnectPortals")]
	internal static class Game_ConnectPortals
	{
		private static bool Prepare()
		{
			return ValheimCompat.RequireMethod(typeof(Game), "ConnectPortals", "portal destinations");
		}

		private static bool Prefix()
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(Game), "ConnectPortalsCoroutine")]
	internal static class Game_ConnectPortalsCoroutine
	{
		private static bool Prepare()
		{
			return ValheimCompat.RequireMethod(typeof(Game), "ConnectPortalsCoroutine", "portal destinations");
		}

		private static bool Prefix()
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(Piece), "SetCreator")]
	internal static class Piece_SetCreator
	{
		private static void Postfix(Piece __instance)
		{
			//IL_0043: 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)
			if (!((Object)(object)__instance == (Object)null) && __instance.m_name != null && __instance.m_name.Contains("$piece_portal"))
			{
				ZNetView nview = __instance.m_nview;
				ZDO val = (((Object)(object)nview != (Object)null) ? nview.GetZDO() : null);
				if (val != null)
				{
					PortalManager.OnPortalPlaced(val.m_uid, val.GetPosition());
				}
			}
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "GetHoverText")]
	internal static class TeleportWorld_GetHoverText
	{
		private static bool Prefix(TeleportWorld __instance, ref string __result)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			ZNetView nview = __instance.m_nview;
			if (Env.ShuttingDown || (Object)(object)nview == (Object)null || nview.GetZDO() == null)
			{
				__result = string.Empty;
				return false;
			}
			ZDO zDO = nview.GetZDO();
			__result = PortalManager.BuildHoverText(zDO.m_uid, zDO.GetPosition());
			return false;
		}
	}
	[HarmonyPatch(typeof(TeleportWorld), "Teleport")]
	internal static class TeleportWorld_Teleport
	{
		private static void Postfix(TeleportWorld __instance)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			ZNetView nview = __instance.m_nview;
			ZDO val = (((Object)(object)nview != (Object)null) ? nview.GetZDO() : null);
			if (val != null)
			{
				PortalManager.RecordUsed(val.GetConnectionZDOID((ConnectionType)1));
			}
		}
	}
	[HarmonyPatch(typeof(TextInput), "RequestText")]
	internal static class TextInput_RequestText
	{
		private static bool Prefix(TextReceiver sign)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			TeleportWorld val = (TeleportWorld)(object)((sign is TeleportWorld) ? sign : null);
			if (val != null)
			{
				ZNetView nview = val.m_nview;
				ZDO val2 = (((Object)(object)nview != (Object)null) ? nview.GetZDO() : null);
				if (val2 != null)
				{
					PortalManager.OnPortalInteract(val2.m_uid);
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(WearNTear), "Destroy")]
	internal static class WearNTear_Destroy
	{
		private static void Prefix(WearNTear __instance)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			Piece val = (((Object)(object)__instance != (Object)null) ? __instance.m_piece : null);
			if (!((Object)(object)val == (Object)null) && val.m_name != null && val.m_name.Contains("$piece_portal") && val.CanBeRemoved())
			{
				ZNetView nview = val.m_nview;
				ZDO val2 = (((Object)(object)nview != (Object)null) ? nview.GetZDO() : null);
				if (val2 != null)
				{
					PortalManager.OnPortalDestroyed(val2.m_uid);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ZDOMan), "ConnectPortals")]
	internal static class ZDOMan_ConnectPortals
	{
		private static bool Prepare()
		{
			return ValheimCompat.RequireMethod(typeof(ZDOMan), "ConnectPortals", "portal destinations");
		}

		private static bool Prefix()
		{
			PortalZdo.RestoreConnections();
			return false;
		}
	}
}
namespace RossPortals.Game.Framework
{
	internal readonly struct CompatMember
	{
		public string Type { get; }

		public string Member { get; }

		public string Why { get; }

		public CompatMember(string type, string member, string why)
		{
			Type = type;
			Member = member;
			Why = why;
		}
	}
	internal static class ValheimCompat
	{
		private static readonly CompatMember[] Members = new CompatMember[23]
		{
			new CompatMember("TeleportWorld", "GetHoverText", "replace portal hover text"),
			new CompatMember("TeleportWorld", "Teleport", "note recently-used destinations"),
			new CompatMember("TeleportWorld", "m_nview", "reach a portal's ZDO"),
			new CompatMember("TextInput", "RequestText", "open our panel instead of the tag box"),
			new CompatMember("ZDOMan", "GetPortalList", "enumerate every portal (server)"),
			new CompatMember("ZDOMan", "ConnectPortals", "rebuild connections from stored destinations"),
			new CompatMember("ZDOMan", "GetZDO", "resolve a portal by id"),
			new CompatMember("ZDOMan", "GetSessionID", "own a portal ZDO before writing it"),
			new CompatMember("ZDOMan", "ForceSendZDO", "push a just-placed portal to the server"),
			new CompatMember("ZDO", "GetConnectionZDOID", "read a portal's live destination"),
			new CompatMember("ZDO", "SetConnection", "set the destination vanilla teleport reads"),
			new CompatMember("ZDO", "GetString", "read the portal tag/name"),
			new CompatMember("ZDO", "GetZDOID", "read stored destination/previous id"),
			new CompatMember("ZDO", "SetOwner", "own a portal ZDO before writing it"),
			new CompatMember("ZDO", "GetPosition", "a portal's world position"),
			new CompatMember("ZDOVars", "s_tag", "the vanilla portal-name ZDO key"),
			new CompatMember("ZRoutedRpc", "InvokeRoutedRPC", "sync the portal list"),
			new CompatMember("ZRoutedRpc", "Everybody", "broadcast to all peers"),
			new CompatMember("Piece", "SetCreator", "detect a placed portal"),
			new CompatMember("Piece", "CanBeRemoved", "confirm a portal is actually being removed"),
			new CompatMember("WearNTear", "Destroy", "detect a removed portal"),
			new CompatMember("Game", "ConnectPortals", "suppress vanilla tag pairing"),
			new CompatMember("Game", "ConnectPortalsCoroutine", "suppress vanilla tag pairing")
		};

		public static void Verify()
		{
			List<string> list = FindMissing(Members);
			if (list.Count == 0)
			{
				RossPortalsPlugin.Log.LogInfo((object)$"Valheim compatibility check: all {Members.Length} referenced members present.");
				return;
			}
			RossPortalsPlugin.Log.LogError((object)($"Valheim compatibility check: {list.Count} of {Members.Length} referenced members are MISSING. " + "The affected features are disabled. This usually means a Valheim update moved something:"));
			foreach (string item in list)
			{
				RossPortalsPlugin.Log.LogError((object)("  - " + item));
			}
		}

		public static List<string> FindMissing(IEnumerable<CompatMember> members)
		{
			List<string> list = new List<string>();
			if (members == null)
			{
				return list;
			}
			foreach (CompatMember member in members)
			{
				Type type = AccessTools.TypeByName(member.Type);
				if (type == null)
				{
					list.Add(member.Type + " (whole type) -- " + member.Why);
				}
				else if (!HasMember(type, member.Member))
				{
					list.Add(member.Type + "." + member.Member + " -- " + member.Why);
				}
			}
			return list;
		}

		private static bool HasMember(Type type, string name)
		{
			Type type2 = type;
			while (type2 != null)
			{
				if (type2.GetField(name, AccessTools.all) != null)
				{
					return true;
				}
				if (type2.GetProperty(name, AccessTools.all) != null)
				{
					return true;
				}
				if (type2.GetEvent(name, AccessTools.all) != null)
				{
					return true;
				}
				try
				{
					if (type2.GetMethod(name, AccessTools.all) != null)
					{
						return true;
					}
				}
				catch (AmbiguousMatchException)
				{
					return true;
				}
				type2 = type2.BaseType;
			}
			return false;
		}

		public static bool RequireMethod(Type type, string method, string featureName)
		{
			if (HasMethod(type, method))
			{
				return true;
			}
			RossPortalsPlugin.Log.LogError((object)(type.Name + "." + method + " not found -- skipping that patch; " + featureName + " will not work. See the compatibility check above."));
			return false;
		}

		private static bool HasMethod(Type type, string name)
		{
			Type type2 = type;
			while (type2 != null)
			{
				if (type2.GetMethods(AccessTools.all).Any((MethodInfo m) => m.Name == name))
				{
					return true;
				}
				type2 = type2.BaseType;
			}
			return false;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}