Decompiled source of FastLink v1.4.6

FastLink.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Net.Sockets;
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;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FastLink.Net;
using FastLink.Patches;
using FastLink.Util;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Splatform;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("FastLink")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Azumatt")]
[assembly: AssemblyProduct("FastLink")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("089A0531-9441-424D-B144-98C1CE1D4D41")]
[assembly: AssemblyFileVersion("1.4.6")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.6.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
namespace FastLink
{
	[HarmonyPatch]
	public static class ZInput_Float_PreventMouseInput
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(ZInput), "GetJoyLeftStickX", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ZInput), "GetJoyLeftStickY", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ZInput), "GetJoyRTrigger", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ZInput), "GetJoyLTrigger", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ZInput), "GetJoyRightStickX", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ZInput), "GetJoyRightStickY", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(ZInput), "GetMouseScrollWheel", (Type[])null, (Type[])null);
		}

		[HarmonyPriority(0)]
		private static void Postfix(ref float __result)
		{
			if (Functions.MHasFocus)
			{
				__result = 0f;
			}
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "UpdateGamepad")]
	internal static class HandleGamepadPatch
	{
		private static bool Prefix(FejdStartup __instance)
		{
			GameObject fastlink = SetupGui.Fastlink;
			if ((Object)(object)fastlink == (Object)null || !fastlink.activeInHierarchy)
			{
				return true;
			}
			if (!ZInput.IsGamepadActive())
			{
				Functions.FocusFastLink(focus: false);
				return true;
			}
			bool flag = false;
			if (Input.GetKeyDown((KeyCode)335))
			{
				Functions.FocusFastLink(focus: true);
				flag = true;
			}
			if (!Functions.MHasFocus)
			{
				return !flag;
			}
			if (ZInput.GetButtonDown("JoyLStickDown") || ZInput.GetButtonDown("JoyDPadDown"))
			{
				Functions.MoveSelection(1);
				flag = true;
			}
			if (ZInput.GetButtonDown("JoyLStickUp") || ZInput.GetButtonDown("JoyDPadUp"))
			{
				Functions.MoveSelection(-1);
				flag = true;
			}
			if (Input.GetKeyDown((KeyCode)330))
			{
				Functions.SubmitSelection();
				flag = true;
			}
			if (Input.GetKeyDown((KeyCode)331) || Input.GetKeyDown((KeyCode)334))
			{
				Functions.FocusFastLink(focus: false);
				flag = true;
			}
			return !flag;
		}
	}
	public class Definition
	{
		public string serverName;

		public ushort port { get; set; }

		public string address { get; set; }

		public bool ispvp { get; set; }

		public bool iscrossplay { get; set; }

		public string password { get; set; } = "";


		public bool iswhitelisted { get; set; }

		public static IEnumerable<Definition> Parse(string yaml)
		{
			return new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, Definition>>(yaml)
				.Select(delegate(KeyValuePair<string, Definition> kv)
				{
					Definition value = kv.Value;
					value.serverName = kv.Key;
					return value;
				});
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder(256);
			stringBuilder.Append(Environment.NewLine);
			if (FastLinkPlugin.HideIP.Value == FastLinkPlugin.Toggle.On)
			{
				stringBuilder.Append("Address: Hidden In Configs");
				stringBuilder.Append(Environment.NewLine);
				stringBuilder.Append("Port: Hidden In Configs");
			}
			else
			{
				stringBuilder.Append("Address: " + address);
				stringBuilder.Append(Environment.NewLine);
				stringBuilder.Append($"Port: {port}");
			}
			stringBuilder.Append(Environment.NewLine);
			stringBuilder.Append($"PvP: {ispvp}");
			stringBuilder.Append(Environment.NewLine);
			stringBuilder.Append($"Crossplay Enabled: {iscrossplay}");
			if (FastLinkPlugin.ShowPasswordInTooltip.Value == FastLinkPlugin.Toggle.On)
			{
				stringBuilder.Append(Environment.NewLine);
				stringBuilder.Append("Password: " + password);
			}
			stringBuilder.Append(Environment.NewLine);
			stringBuilder.Append($"Uses Whitelisted Player List: {iswhitelisted}");
			return stringBuilder.ToString();
		}
	}
	[BepInPlugin("Azumatt.FastLink", "FastLink", "1.4.6")]
	public class FastLinkPlugin : BaseUnityPlugin
	{
		public enum Toggle
		{
			Off,
			On
		}

		internal sealed class ConfigurationManagerAttributes
		{
			public Action<ConfigEntryBase> CustomDrawer;

			public bool? HideDefaultButton;

			public bool? HideSettingName;

			public string Description = "";
		}

		internal const string ModName = "FastLink";

		internal const string ModVersion = "1.4.6";

		internal const string Author = "Azumatt";

		private const string ModGUID = "Azumatt.FastLink";

		private static string ConfigFileName = "Azumatt.FastLink.cfg";

		private static string ConfigFileFullPath;

		internal static FastLinkPlugin instance;

		internal readonly Harmony _harmony = new Harmony("Azumatt.FastLink");

		public static readonly ManualLogSource FastLinkLogger;

		public static ConfigEntry<Vector2> UIAnchor;

		public static ConfigEntry<Vector2> MerchUIAnchor;

		public static ConfigEntry<Vector3> LocalScale;

		public static ConfigEntry<Toggle> Sort;

		public static ConfigEntry<Toggle> HideIP;

		public static ConfigEntry<Toggle> ShowPasswordPrompt;

		public static ConfigEntry<Toggle> ShowPasswordInTooltip;

		private const int WindowId = -70;

		internal static Rect ScreenRect;

		internal static string EditorText;

		internal static Vector2 SettingWindowScrollPos;

		internal static bool RichTextOn;

		private Rect ContentWindowRect { get; set; }

		private void Awake()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_011a: 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_0134: Expected O, but got Unknown
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Expected O, but got Unknown
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Expected O, but got Unknown
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Expected O, but got Unknown
			instance = this;
			((BaseUnityPlugin)this).Config.Bind<string>("General", "FastLink URL", "https://valheim.thunderstore.io/package/Azumatt/FastLink/", new ConfigDescription("Link to the mod page", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					HideSettingName = true,
					HideDefaultButton = true,
					Description = "Edit the " + Servers.ConfigFileName + " directly from the configuration manager.",
					CustomDrawer = Functions.EditServersButton
				}
			}));
			Sort = ((BaseUnityPlugin)this).Config.Bind<Toggle>("General", "Sort List Alphabetically", Toggle.On, new ConfigDescription("Sorts the Server List Alphabetically. If disabled, the list will be displayed in the same order as the file. NOTE: If you are using colors in your server name, if on, it will still sort but the color you use will have an affect on on the order.", (AcceptableValueBase)null, Array.Empty<object>()));
			Sort.SettingChanged += delegate
			{
				ReadNewServers(null, null);
			};
			HideIP = ((BaseUnityPlugin)this).Config.Bind<Toggle>("General", "Hide the IP in the panel", Toggle.Off, new ConfigDescription("Turn on to hide the IP in the connection panel at the main menu. Also hides it in the tooltip", (AcceptableValueBase)null, Array.Empty<object>()));
			HideIP.SettingChanged += delegate
			{
				ReadNewServers(null, null);
			};
			UIAnchor = ((BaseUnityPlugin)this).Config.Bind<Vector2>("UI", "Position of the UI", new Vector2(429f, 172f), new ConfigDescription("Sets the anchor position of the UI. You can drag it by left clicking on the title and dragging. Manual setting here is also available.", (AcceptableValueBase)null, Array.Empty<object>()));
			UIAnchor.SettingChanged += SaveAndReset;
			MerchUIAnchor = ((BaseUnityPlugin)this).Config.Bind<Vector2>("UI", "Position of the Merch UI", new Vector2(-152f, 270f), new ConfigDescription("Sets the anchor position of the Merch UI. You can drag it by left clicking on the title and dragging. Manual setting here is also available. Vanilla is -200, -155", (AcceptableValueBase)null, Array.Empty<object>()));
			MerchUIAnchor.SettingChanged += SaveAndReset;
			LocalScale = ((BaseUnityPlugin)this).Config.Bind<Vector3>("UI", "LocalScale of the UI", new Vector3(1f, 1f, 1f), new ConfigDescription("Sets the local scale the UI. This is overall size of the UI. Defaults to vanilla JoinGame UI size. I prefer 0.85, 0.85, 0.85", (AcceptableValueBase)null, Array.Empty<object>()));
			LocalScale.SettingChanged += SaveAndReset;
			ShowPasswordPrompt = ((BaseUnityPlugin)this).Config.Bind<Toggle>("General", "Show Password Prompt", Toggle.Off, new ConfigDescription("Set to true if you want to still show the password prompt to the user. This is for servers that have a password but don't wish to use the file to keep the password.", (AcceptableValueBase)null, Array.Empty<object>()));
			ShowPasswordInTooltip = ((BaseUnityPlugin)this).Config.Bind<Toggle>("General", "Show Password In Tooltip", Toggle.Off, new ConfigDescription("Set to true if you want to show the password inside the tooltip hover.", (AcceptableValueBase)null, Array.Empty<object>()));
			ShowPasswordInTooltip.SettingChanged += delegate
			{
				ReadNewServers(null, null);
			};
			LoadTooltipAsset("fastlink");
			_harmony.PatchAll();
			SetupWatcher();
		}

		private void Start()
		{
			Game.isModded = true;
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}

		private void SetupWatcher()
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
			fileSystemWatcher.Changed += ReadConfigValues;
			fileSystemWatcher.Created += ReadConfigValues;
			fileSystemWatcher.Renamed += ReadConfigValues;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
			FileSystemWatcher fileSystemWatcher2 = new FileSystemWatcher(Paths.ConfigPath, Servers.ConfigFileName);
			fileSystemWatcher2.Changed += ReadNewServers;
			fileSystemWatcher2.Created += ReadNewServers;
			fileSystemWatcher2.Renamed += ReadNewServers;
			fileSystemWatcher2.IncludeSubdirectories = true;
			fileSystemWatcher2.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher2.EnableRaisingEvents = true;
		}

		private void ReadConfigValues(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(ConfigFileFullPath))
			{
				return;
			}
			try
			{
				FastLinkLogger.LogDebug((object)"ReadConfigValues called");
				((BaseUnityPlugin)this).Config.Reload();
			}
			catch
			{
				FastLinkLogger.LogError((object)("There was an issue loading your " + ConfigFileName));
				FastLinkLogger.LogError((object)"Please check your config entries for spelling and format!");
			}
		}

		private void ReadNewServers(object sender, FileSystemEventArgs e)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if (!File.Exists(Servers.ConfigPath))
			{
				return;
			}
			try
			{
				FastLinkLogger.LogDebug((object)"Reloading Server List");
				SetupGui.Connecting = null;
				foreach (GameObject mServerListElement in SetupGui.MServerListElements)
				{
					Object.Destroy((Object)(object)mServerListElement);
				}
				SetupGui.MServerListElements.Clear();
				Servers.Init();
				Functions.AbortConnect();
				Functions.PopulateServerList(SetupGui.Fastlink);
				Functions.UpdateServerList();
				SetupGui.MJoinServer = null;
			}
			catch
			{
				if (!((Object)(object)Player.m_localPlayer == (Object)null))
				{
					Scene activeScene = SceneManager.GetActiveScene();
					if (!(((Scene)(ref activeScene)).name != "main"))
					{
						return;
					}
				}
				FastLinkLogger.LogError((object)("There was an issue loading your " + Servers.ConfigFileName));
				FastLinkLogger.LogError((object)"Please check your config entries for spelling and format!");
			}
		}

		private void SaveAndReset(object sender, EventArgs e)
		{
			//IL_001a: 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_0033: 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)
			((BaseUnityPlugin)this).Config.Save();
			SetupGui.FastlinkRootGo.GetComponent<RectTransform>().anchoredPosition = new Vector2(UIAnchor.Value.x, UIAnchor.Value.y);
			SetupGui.Fastlink.gameObject.transform.localScale = LocalScale.Value;
		}

		private void LoadTooltipAsset(string bundleName)
		{
			AssetBundle assetBundleFromResources = GetAssetBundleFromResources(bundleName);
			SetupGui.FastlinkTooltip = assetBundleFromResources.LoadAsset<GameObject>("FastLinkTooltip");
			if (assetBundleFromResources != null)
			{
				assetBundleFromResources.Unload(false);
			}
		}

		private static AssetBundle GetAssetBundleFromResources(string filename)
		{
			string filename2 = filename;
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(filename2));
			using Stream stream = executingAssembly.GetManifestResourceStream(name);
			return AssetBundle.LoadFromStream(stream);
		}

		private void Update()
		{
			Functions.ShouldShowCursor();
		}

		private void LateUpdate()
		{
			Functions.ShouldShowCursor();
		}

		private void OnGUI()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_00c0: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			if (EditorText.Length > 0)
			{
				Functions.ShouldShowCursor();
				int num = Mathf.Min(Screen.width, 1000);
				int num2 = ((Screen.height < 560) ? Screen.height : (Screen.height - 200));
				int num3 = Mathf.RoundToInt((float)(Screen.width - num) / 2f);
				int num4 = Mathf.RoundToInt((float)(Screen.height - num2) / 2f);
				ContentWindowRect = new Rect((float)num3, (float)num4, (float)num, (float)num2);
				ScreenRect = new Rect(0f, 0f, (float)Screen.width, (float)Screen.height);
				GUILayout.Window(-70, ContentWindowRect, new WindowFunction(DoServerWindow), "FastLink Servers", Array.Empty<GUILayoutOption>());
			}
		}

		private void DoServerWindow(int id)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0027: Invalid comparison between Unknown and I4
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Invalid comparison between Unknown and I4
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Invalid comparison between Unknown and I4
			Functions.MakeShitDarkerInABadWay();
			bool flag = GUI.GetNameOfFocusedControl() == "FastLinkEditor";
			if (flag)
			{
				EventType type = Event.current.type;
				bool flag2 = type - 4 <= 1;
				flag = flag2;
			}
			if (flag && Event.current.isKey)
			{
				TextEditor val = (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl);
				if ((int)Event.current.keyCode == 9)
				{
					if ((int)Event.current.type == 5)
					{
						val.text += "    ";
						val.MoveLineEnd();
						EditorText = val.text;
					}
					Event.current.Use();
				}
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUI.backgroundColor = Color.white;
			Functions.BuildContentScroller();
			GUI.backgroundColor = Color.green;
			GUI.contentColor = Color.white;
			Functions.BuildButtons();
			GUILayout.EndHorizontal();
		}

		static FastLinkPlugin()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName;
			instance = null;
			FastLinkLogger = Logger.CreateLogSource("FastLink");
			UIAnchor = null;
			MerchUIAnchor = null;
			LocalScale = null;
			Sort = null;
			HideIP = null;
			ShowPasswordPrompt = null;
			ShowPasswordInTooltip = null;
			EditorText = "";
		}
	}
}
namespace FastLink.Util
{
	public class DragControl : MonoBehaviour, IDragHandler, IEventSystemHandler, IEndDragHandler
	{
		[SerializeField]
		private RectTransform dragRectTransform = new RectTransform();

		private void Start()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			dragRectTransform = ((Component)this).GetComponent<RectTransform>();
			dragRectTransform.anchoredPosition = FastLinkPlugin.UIAnchor.Value;
		}

		public void OnDrag(PointerEventData eventData)
		{
			//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_0012: Unknown result type (might be due to invalid IL or missing references)
			RectTransform obj = dragRectTransform;
			obj.anchoredPosition += eventData.delta;
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			FastLinkPlugin.UIAnchor.Value = dragRectTransform.anchoredPosition;
		}
	}
	public class MerchAreaDragControl : MonoBehaviour, IDragHandler, IEventSystemHandler, IEndDragHandler
	{
		[SerializeField]
		private RectTransform dragRectTransform = new RectTransform();

		[SerializeField]
		private Button[] buttons;

		private void Start()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			dragRectTransform = ((Component)this).GetComponent<RectTransform>();
			buttons = ((Component)this).GetComponentsInChildren<Button>();
			dragRectTransform.anchoredPosition = FastLinkPlugin.MerchUIAnchor.Value;
		}

		public void OnDrag(PointerEventData eventData)
		{
			//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)
			Button[] array = buttons;
			for (int i = 0; i < array.Length; i++)
			{
				((Selectable)array[i]).interactable = false;
			}
			RectTransform obj = dragRectTransform;
			obj.anchoredPosition += eventData.delta;
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			Button[] array = buttons;
			for (int i = 0; i < array.Length; i++)
			{
				((Selectable)array[i]).interactable = true;
			}
			FastLinkPlugin.MerchUIAnchor.Value = dragRectTransform.anchoredPosition;
		}
	}
	public static class Functions
	{
		private sealed class FastLinkPanelPulse : MonoBehaviour
		{
			private CanvasGroup _cg;

			private bool _on;

			public void Init(CanvasGroup cg)
			{
				_cg = cg;
			}

			public void SetOn(bool on)
			{
				_on = on;
				if (!on && Object.op_Implicit((Object)(object)_cg))
				{
					_cg.alpha = 0f;
				}
			}

			private void Update()
			{
				if (_on && Object.op_Implicit((Object)(object)_cg))
				{
					float alpha = 0.45f + 0.4f * Mathf.PingPong(Time.unscaledTime * 1.6f, 1f);
					_cg.alpha = alpha;
				}
			}
		}

		internal static bool MHasFocus = false;

		internal static int MSelectedIndex = -1;

		private static GameObject _panelChrome;

		private static CanvasGroup _panelChromeCg;

		private static FastLinkPanelPulse _panelPulse;

		private static TMP_Text _focusHint;

		private static readonly Color PanelLineColor = new Color(1f, 0.85f, 0.2f, 1f);

		private static readonly Color FocusBarColor = new Color(1f, 0.85f, 0.2f, 0.95f);

		private static readonly Color FocusFillColor = new Color(1f, 0.85f, 0.2f, 0.18f);

		private static readonly Color NameFocusedColor = Color.white;

		private static readonly Color NameNormalColor = new Color(0.88f, 0.88f, 0.88f, 1f);

		internal static void FocusFastLink(bool focus)
		{
			MHasFocus = focus;
			if (focus)
			{
				if (SetupGui.MServerList.Count > 0 && (MSelectedIndex < 0 || MSelectedIndex >= SetupGui.MServerList.Count))
				{
					MSelectedIndex = 0;
				}
				SyncJoinDataWithSelection();
				UpdateServerListGui(centerSelection: false);
			}
			UpdatePanelFocusChrome(focus);
		}

		internal static void MoveSelection(int delta)
		{
			if (MHasFocus && SetupGui.MServerList.Count != 0)
			{
				int num = Mathf.Clamp(((MSelectedIndex >= 0) ? MSelectedIndex : 0) + delta, 0, SetupGui.MServerList.Count - 1);
				if (num != MSelectedIndex)
				{
					MSelectedIndex = num;
					SyncJoinDataWithSelection();
					UpdateServerListGui(centerSelection: true);
				}
			}
		}

		internal static void SubmitSelection()
		{
			if (MHasFocus && MSelectedIndex >= 0 && MSelectedIndex < SetupGui.MServerList.Count)
			{
				Definition definition = (SetupGui.MJoinServer = SetupGui.MServerList[MSelectedIndex]);
				Connect(new Definition
				{
					serverName = definition.serverName,
					address = definition.address,
					port = definition.port,
					password = definition.password
				});
				UpdateServerListGui(centerSelection: false);
			}
		}

		private static void SyncJoinDataWithSelection()
		{
			//IL_004e: 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)
			if (MSelectedIndex >= 0 && MSelectedIndex < SetupGui.MServerList.Count)
			{
				Definition definition = SetupGui.MServerList[MSelectedIndex];
				ServerJoinDataDedicated val = default(ServerJoinDataDedicated);
				((ServerJoinDataDedicated)(ref val))..ctor($"{definition.address}:{definition.port}");
				ServerJoinData serverToJoin = default(ServerJoinData);
				((ServerJoinData)(ref serverToJoin))..ctor(val);
				FejdStartup instance = FejdStartup.instance;
				if (instance != null)
				{
					instance.SetServerToJoin(serverToJoin);
				}
			}
		}

		public static void BuildPanelFocusChrome(GameObject panel)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: 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_0153: 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_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_panelChrome))
			{
				Object.Destroy((Object)(object)_panelChrome);
			}
			RectTransform component = panel.GetComponent<RectTransform>();
			_panelChrome = new GameObject("FastLinkPanelChrome", new Type[2]
			{
				typeof(RectTransform),
				typeof(CanvasGroup)
			});
			RectTransform component2 = _panelChrome.GetComponent<RectTransform>();
			((Transform)component2).SetParent(((Transform)component).Find("ServerList"), false);
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = Vector2.zero;
			component2.offsetMax = Vector2.zero;
			_panelChrome.transform.SetAsLastSibling();
			_panelChromeCg = _panelChrome.GetComponent<CanvasGroup>();
			_panelChromeCg.interactable = false;
			_panelChromeCg.blocksRaycasts = false;
			_panelChromeCg.alpha = 0f;
			CreateEdge("Top", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, 2f));
			CreateEdge("Bottom", new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0f, 2f));
			CreateEdge("Left", new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(2f, 0f));
			CreateEdge("Right", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(2f, 0f));
			Transform val = panel.transform.Find("topic");
			if ((Object)(object)val != (Object)null)
			{
				GameObject val2 = new GameObject("FastLinkGamepadHint", new Type[2]
				{
					typeof(RectTransform),
					typeof(TextMeshProUGUI)
				});
				RectTransform component3 = val2.GetComponent<RectTransform>();
				((Transform)component3).SetParent(val, false);
				component3.anchoredPosition = new Vector2(0f, -44f);
				_focusHint = (TMP_Text)(object)val2.GetComponent<TextMeshProUGUI>();
				_focusHint.text = "Focused • A: Join  B/LB: Back  D-Pad/LS: Navigate";
				_focusHint.font = ((Component)val).GetComponent<TMP_Text>().font;
				_focusHint.fontSize = 18f;
				_focusHint.alignment = (TextAlignmentOptions)544;
				_focusHint.enableWordWrapping = false;
				((Graphic)_focusHint).color = new Color(1f, 0.85f, 0.2f, 0.95f);
				((Component)_focusHint).gameObject.SetActive(false);
			}
			_panelPulse = _panelChrome.AddComponent<FastLinkPanelPulse>();
			_panelPulse.Init(_panelChromeCg);
		}

		private static void CreateEdge(string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 sizeDelta)
		{
			//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_0044: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform component = val.GetComponent<RectTransform>();
			Image component2 = val.GetComponent<Image>();
			((Transform)component).SetParent(_panelChrome.transform, false);
			component.anchorMin = anchorMin;
			component.anchorMax = anchorMax;
			component.sizeDelta = sizeDelta;
			component.anchoredPosition = Vector2.zero;
			((Graphic)component2).raycastTarget = false;
			((Graphic)component2).color = PanelLineColor;
		}

		public static void UpdatePanelFocusChrome(bool focused)
		{
			if (Object.op_Implicit((Object)(object)_panelChromeCg))
			{
				_panelPulse?.SetOn(focused);
				_panelChromeCg.alpha = (focused ? 0.6f : 0f);
				if (Object.op_Implicit((Object)(object)_focusHint))
				{
					_focusHint.text = (focused ? "Focused • A: Join  B/LB: Back  D-Pad/LS: Navigate" : "Press RB to focus");
					((Component)_focusHint).gameObject.SetActive(ZInput.IsGamepadActive());
				}
			}
		}

		internal static void ApplyStatusToRow(int index, Definition server, ServerListEntryData entry)
		{
			//IL_0047: 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)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: 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_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			if (index < 0 || index >= SetupGui.MServerListElements.Count)
			{
				return;
			}
			GameObject val = SetupGui.MServerListElements[index];
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			TMP_Text componentInChildren = val.GetComponentInChildren<TMP_Text>();
			if ((Object)(object)componentInChildren == (Object)null)
			{
				return;
			}
			componentInChildren.text = $"{index + 1}. {entry.m_serverName}";
			val.GetComponentInChildren<TMP_Text>().text = $"{index + 1}. {server.serverName}";
			val.GetComponentInChildren<UITooltip>().Set(server.serverName, server.ToString(), (RectTransform)null, default(Vector2));
			TMP_Text component = ((Component)val.transform.Find("players")).GetComponent<TMP_Text>();
			if (((ServerListEntryData)(ref entry)).IsOnline && ((ServerListEntryData)(ref entry)).HasMatchmakingData)
			{
				component.text = $"{entry.m_playerCount} / {entry.m_playerLimit}";
			}
			else if (((ServerListEntryData)(ref entry)).IsAvailable)
			{
				component.text = "—";
			}
			else
			{
				component.text = "";
			}
			TMP_Text component2 = ((Component)val.transform.Find("version")).GetComponent<TMP_Text>();
			if (((ServerListEntryData)(ref entry)).HasMatchmakingData)
			{
				component2.text = $"{entry.m_gameVersion}";
			}
			else
			{
				component2.text = ((FastLinkPlugin.HideIP.Value == FastLinkPlugin.Toggle.On) ? "" : server.port.ToString());
			}
			TMP_Text component3 = ((Component)val.transform.Find("modifiers")).GetComponent<TMP_Text>();
			if (FastLinkPlugin.HideIP.Value == FastLinkPlugin.Toggle.On)
			{
				component3.text = "Hidden";
			}
			else
			{
				component3.text = server.address;
			}
			((Component)val.transform.Find("Private")).gameObject.SetActive((((ServerListEntryData)(ref entry)).HasMatchmakingData && ((ServerListEntryData)(ref entry)).IsPasswordProtected) || (!((ServerListEntryData)(ref entry)).HasMatchmakingData && server.password.Length > 1));
			((Component)val.transform.Find("crossplay")).gameObject.SetActive(((ServerListEntryData)(ref entry)).IsCrossplay);
			Transform val2 = val.transform.Find("status");
			if (Object.op_Implicit((Object)(object)val2))
			{
				((Component)val2).gameObject.SetActive(true);
				GameObject obj = GameObject.Find("GUI/StartGui/StartGame/Panel/JoinPanel");
				ServerListGui val3 = ((obj != null) ? obj.GetComponent<ServerListGui>() : null);
				if ((Object)(object)val3 != (Object)null)
				{
					ConnectIcons connectIcons = val3.m_connectIcons;
					((Component)val2).GetComponent<Image>().sprite = ((!((ServerListEntryData)(ref entry)).HasMatchmakingData) ? connectIcons.m_trying : (((ServerListEntryData)(ref entry)).IsOnline ? connectIcons.m_success : ((!((ServerListEntryData)(ref entry)).IsAvailable) ? connectIcons.m_unknown : connectIcons.m_failed)));
				}
			}
		}

		internal static void DestroyAll(GameObject thing)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			Object.DestroyImmediate((Object)(object)((Component)thing.transform.Find("FilterField")).gameObject);
			Object.DestroyImmediate((Object)(object)((Component)thing.transform.Find("Refresh")).gameObject);
			Object.DestroyImmediate((Object)(object)((Component)thing.transform.Find("Server help")).gameObject);
			Object.DestroyImmediate((Object)(object)((Component)thing.transform.Find("Back")).gameObject);
			Object.DestroyImmediate((Object)(object)((Component)thing.transform.Find("Join")).gameObject);
			foreach (Transform item in thing.transform)
			{
				Transform val = item;
				if (((Object)val).name.StartsWith("ServerListTab(Clone)"))
				{
					Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
				}
			}
			Object.DestroyImmediate((Object)(object)((Component)thing.transform.Find("Add server")).gameObject);
			Object.DestroyImmediate((Object)(object)((Component)thing.transform.Find("FavoriteButton")).gameObject);
		}

		internal static void PopulateServerList(GameObject linkpanel)
		{
			//IL_0073: 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_00ad: 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)
			FastLinkPlugin.FastLinkLogger.LogDebug((object)"POPULATE SERVER LIST");
			SetupGui.MServerListElement = ((Component)linkpanel.transform.Find("ServerList/ServerElement")).gameObject;
			((Behaviour)((Component)linkpanel.transform.Find("ServerList")).gameObject.GetComponent<Image>()).enabled = false;
			GameObject gameObject = GameObject.Find("GuiRoot/GUI/StartGui/FastLink/JoinPanel(Clone)/ServerList/ListRoot").gameObject;
			gameObject.gameObject.transform.localScale = new Vector3(1f, 0.8f, 1f);
			SetupGui.MServerListRoot = gameObject.GetComponent<RectTransform>();
			gameObject.gameObject.GetComponent<RectTransform>().pivot = new Vector2(gameObject.gameObject.GetComponent<RectTransform>().pivot.x, 1f);
			SetupGui.MServerCount = ((Component)linkpanel.transform.Find("serverCount")).gameObject.GetComponent<TextMeshProUGUI>();
			Rect rect = SetupGui.MServerListRoot.rect;
			SetupGui.MServerListBaseSize = ((Rect)(ref rect)).height;
		}

		internal static void UpdateServerList()
		{
			FastLinkPlugin.FastLinkLogger.LogDebug((object)"UPDATE SERVER LIST");
			SetupGui.MServerList.Clear();
			if (SetupGui.Connecting != null)
			{
				FastLinkPlugin.FastLinkLogger.LogDebug((object)"Connecting not null");
				AbortConnect();
			}
			else if (Servers.entries.Count > 0)
			{
				foreach (Definition entry in Servers.entries)
				{
					SetupGui.MServerList.Add(entry);
				}
			}
			else
			{
				FastLinkPlugin.FastLinkLogger.LogError((object)"No servers defined");
				FastLinkPlugin.FastLinkLogger.LogError((object)("Please create this file " + Servers.ConfigPath));
			}
			if (FastLinkPlugin.Sort.Value == FastLinkPlugin.Toggle.On)
			{
				SetupGui.MServerList.Sort((Definition a, Definition b) => string.Compare(a?.serverName, b?.serverName, StringComparison.Ordinal));
			}
			if (SetupGui.MJoinServer != null && !SetupGui.MServerList.Contains(SetupGui.MJoinServer))
			{
				FastLinkPlugin.FastLinkLogger.LogDebug((object)"Server list does not contain selected server, clearing selected server");
				SetupGui.MJoinServer = null;
			}
			UpdateServerListGui(centerSelection: false);
		}

		private static void UpdateServerListGui(bool centerSelection)
		{
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			if (SetupGui.MServerList.Count != SetupGui.MServerListElements.Count)
			{
				FastLinkPlugin.FastLinkLogger.LogDebug((object)"UPDATE SERVER LIST GUI");
				foreach (GameObject mServerListElement in SetupGui.MServerListElements)
				{
					Object.DestroyImmediate((Object)(object)mServerListElement);
				}
				SetupGui.MServerListElements.Clear();
				SetupGui.MServerListRoot.SetSizeWithCurrentAnchors((Axis)1, Mathf.Max(SetupGui.MServerListBaseSize, (float)SetupGui.MServerList.Count * SetupGui.m_serverListElementStep));
				for (int i = 0; i < SetupGui.MServerList.Count; i++)
				{
					GameObject gameObject = Object.Instantiate<GameObject>(SetupGui.MServerListElement, (Transform)(object)SetupGui.MServerListRoot);
					gameObject.SetActive(true);
					Transform transform = gameObject.transform;
					((RectTransform)((transform is RectTransform) ? transform : null)).anchoredPosition = new Vector2(0f, (float)i * (0f - SetupGui.m_serverListElementStep));
					((UnityEvent)gameObject.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
					{
						OnSelectedServer(gameObject);
					});
					if (!SetupGui.MServerListElements.Contains(gameObject))
					{
						SetupGui.MServerListElements.Add(gameObject);
					}
					string text = ((SetupGui.MServerListElements.Count > 1) ? " Servers" : " Server");
					if ((Object)(object)SetupGui.MServerCount != (Object)null)
					{
						((TMP_Text)SetupGui.MServerCount).text = SetupGui.MServerListElements.Count + text;
					}
				}
			}
			FastLinkPlugin.FastLinkLogger.LogDebug((object)$"ServerList count: {SetupGui.MServerList.Count}");
			for (int j = 0; j < SetupGui.MServerList.Count; j++)
			{
				Definition definition = SetupGui.MServerList[j];
				GameObject val = SetupGui.MServerListElements?[j];
				if (!((Object)(object)val == (Object)null))
				{
					val.GetComponentInChildren<TMP_Text>().text = $"{j + 1}. {definition.serverName}";
					val.GetComponentInChildren<UITooltip>().Set(definition.serverName, definition.ToString(), (RectTransform)null, default(Vector2));
					string text2 = (((Component)val.transform.Find("players")).GetComponent<TMP_Text>().text = string.Empty);
					TMP_Text component = ((Component)val.transform.Find("modifiers")).GetComponent<TMP_Text>();
					TMP_Text component2 = ((Component)val.transform.Find("version")).GetComponent<TMP_Text>();
					if (FastLinkPlugin.HideIP.Value == FastLinkPlugin.Toggle.On)
					{
						component.text = "Hidden";
						component2.text = "";
					}
					else
					{
						component.text = definition.address;
						component2.text = definition.port.ToString();
					}
					((Component)val.transform.Find("Private")).gameObject.SetActive(definition.password.Length > 1);
					((Component)val.transform.Find("PVP")).gameObject.SetActive(definition.ispvp);
					((Component)val.transform.Find("crossplay")).gameObject.SetActive(definition.iscrossplay);
					((Component)val.transform.Find("status")).gameObject.SetActive(false);
					Transform obj = val.transform.Find("selected");
					ServerStatusService.RequestStatus(definition, j, ApplyStatusToRow);
					bool flag = MHasFocus && MSelectedIndex == j;
					bool flag2 = !MHasFocus && SetupGui.MJoinServer != null && SetupGui.MJoinServer.Equals(definition);
					((Component)obj).gameObject.SetActive(flag || flag2);
				}
			}
		}

		private static void Connect(Definition server)
		{
			FastLinkPlugin.FastLinkLogger.LogDebug((object)"DO CONNECT");
			SetupGui.Connecting = server;
			try
			{
				if (!JoinServer(IPAddress.Parse(server.address), server.port))
				{
					SetupGui.Connecting = null;
					FastLinkPlugin.FastLinkLogger.LogError((object)"Server address was not valid");
				}
			}
			catch (FormatException)
			{
				FastLinkPlugin.FastLinkLogger.LogDebug((object)("Resolving: " + server.address));
				try
				{
					SetupGui.ResolveTask = Dns.GetHostEntryAsync(server.address);
					FastLinkPlugin.FastLinkLogger.LogDebug((object)$"Resolving after task: {SetupGui.ResolveTask.Result.AddressList[0]}");
				}
				catch (Exception)
				{
					FastLinkPlugin.FastLinkLogger.LogError((object)("You are trying to resolve the IP : " + server.address + ", but something is happening causing it to not work properly."));
				}
				if (SetupGui.ResolveTask == null)
				{
					FastLinkPlugin.FastLinkLogger.LogError((object)"Your resolve task was null, fix it you idiot");
				}
				else if (SetupGui.ResolveTask.IsFaulted)
				{
					FastLinkPlugin.FastLinkLogger.LogError((object)$"Error resolving IP: {SetupGui.ResolveTask.Exception}");
					FastLinkPlugin.FastLinkLogger.LogError((object)((SetupGui.ResolveTask.Exception?.InnerException != null) ? SetupGui.ResolveTask.Exception.InnerException.Message : SetupGui.ResolveTask.Exception?.Message));
					SetupGui.ResolveTask = null;
					SetupGui.Connecting = null;
				}
				else if (SetupGui.ResolveTask.IsCanceled)
				{
					FastLinkPlugin.FastLinkLogger.LogError((object)("Error CANCELED: " + SetupGui.ResolveTask.Result.HostName));
					SetupGui.ResolveTask = null;
					SetupGui.Connecting = null;
				}
				else if (SetupGui.ResolveTask.IsCompleted)
				{
					FastLinkPlugin.FastLinkLogger.LogDebug((object)("COMPLETE: " + server.address));
					IPAddress[] addressList = SetupGui.ResolveTask.Result.AddressList;
					int num = 0;
					if (num < addressList.Length)
					{
						IPAddress iPAddress = addressList[num];
						FastLinkPlugin.FastLinkLogger.LogDebug((object)$"Resolved Completed: {iPAddress}");
						SetupGui.ResolveTask = null;
						if (!JoinServer(iPAddress, server.port))
						{
							SetupGui.Connecting = null;
							FastLinkPlugin.FastLinkLogger.LogError((object)"Server DNS resolved to invalid address");
						}
					}
				}
				else
				{
					SetupGui.ResolveTask = null;
					SetupGui.Connecting = null;
					FastLinkPlugin.FastLinkLogger.LogError((object)"Server DNS resolved to no valid addresses");
				}
			}
		}

		private static bool JoinServer(IPAddress address, ushort port)
		{
			//IL_0067: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			string text = $"{((address.AddressFamily == AddressFamily.InterNetworkV6) ? $"[{address}]" : $"{address}")}:{port}";
			FastLinkPlugin.FastLinkLogger.LogDebug((object)("Server and Port passed into JoinServer: " + text));
			if (address.AddressFamily == AddressFamily.InterNetwork)
			{
				address = address.MapToIPv6();
			}
			if (address.AddressFamily != AddressFamily.InterNetworkV6)
			{
				return false;
			}
			SteamNetworkingIPAddr val = default(SteamNetworkingIPAddr);
			((SteamNetworkingIPAddr)(ref val)).SetIPv6(address.GetAddressBytes(), port);
			ZSteamMatchmaking.instance.m_joinData = new ServerJoinData(new ServerJoinDataDedicated(((SteamNetworkingIPAddr)(ref val)).GetIPv4(), port));
			return true;
		}

		public static string? CurrentPass()
		{
			return SetupGui.Connecting?.password;
		}

		public static void AbortConnect()
		{
			FastLinkPlugin.FastLinkLogger.LogDebug((object)"ABORT CONNECT");
			SetupGui.Connecting = null;
			SetupGui.ResolveTask = null;
		}

		private static void OnSelectedServer(GameObject gameObject)
		{
			int num = FindSelectedServer((Object)(object)gameObject);
			if (num >= 0)
			{
				MSelectedIndex = num;
			}
			SetupGui.MJoinServer = SetupGui.MServerList[num];
			Connect(new Definition
			{
				serverName = SetupGui.MJoinServer.serverName,
				address = SetupGui.MJoinServer.address,
				port = SetupGui.MJoinServer.port,
				password = SetupGui.MJoinServer.password
			});
			UpdateServerListGui(centerSelection: false);
		}

		private static int FindSelectedServer(Object button)
		{
			try
			{
				FastLinkPlugin.FastLinkLogger.LogDebug((object)"FIND SELECTED");
				for (int i = 0; i < SetupGui.MServerListElements.Count; i++)
				{
					if (i >= 0 && i < SetupGui.MServerListElements.Count && (Object)(object)SetupGui.MServerListElements[i] == button)
					{
						return i;
					}
				}
				return -1;
			}
			catch (Exception arg)
			{
				FastLinkPlugin.FastLinkLogger.LogDebug((object)$"The issues were found here: {arg}");
			}
			return 1;
		}

		internal static void ShouldShowCursor()
		{
			if (FastLinkPlugin.EditorText.Length > 1)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		internal static void EditServersButton(ConfigEntryBase _)
		{
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			if (File.Exists(Servers.ConfigPath) && Servers.entries.Count > 0 && GUILayout.Button("Edit Servers", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
			{
				FastLinkPlugin.EditorText = File.ReadAllText(Servers.ConfigPath);
			}
			GUILayout.EndVertical();
		}

		internal static void SaveFromEditor()
		{
			try
			{
				File.WriteAllText(Servers.ConfigPath, FastLinkPlugin.EditorText);
				FastLinkPlugin.FastLinkLogger.LogInfo((object)"Saved servers, rebuilding list");
			}
			catch (Exception arg)
			{
				FastLinkPlugin.FastLinkLogger.LogError((object)$"Error saving servers: {arg}");
			}
		}

		internal static void MakeShitDarkerInABadWay()
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 6; i++)
			{
				GUI.Box(FastLinkPlugin.ScreenRect, (Texture)(object)Texture2D.blackTexture);
			}
		}

		internal static void BuildContentScroller()
		{
			//IL_0000: 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_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_002c: 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)
			//IL_004d: Expected O, but got Unknown
			FastLinkPlugin.SettingWindowScrollPos = GUILayout.BeginScrollView(FastLinkPlugin.SettingWindowScrollPos, false, true, Array.Empty<GUILayoutOption>());
			GUI.SetNextControlName("FastLinkEditor");
			GUIStyle val = new GUIStyle
			{
				richText = true
			};
			val.normal.textColor = Color.white;
			val.normal.background = Texture2D.blackTexture;
			GUIStyle val2 = val;
			if (FastLinkPlugin.RichTextOn)
			{
				FastLinkPlugin.EditorText = GUILayout.TextArea(FastLinkPlugin.EditorText, val2, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.ExpandWidth(true),
					GUILayout.ExpandHeight(true)
				});
			}
			else
			{
				FastLinkPlugin.EditorText = GUILayout.TextArea(FastLinkPlugin.EditorText, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.ExpandWidth(true),
					GUILayout.ExpandHeight(true)
				});
			}
			GUILayout.EndScrollView();
		}

		internal static void BuildButtons()
		{
			//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_0094: 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)
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.ExpandWidth(true),
				GUILayout.ExpandHeight(true)
			});
			if (GUILayout.Button(Localization.instance.Localize("$settings_apply"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
			{
				SaveFromEditor();
				FastLinkPlugin.EditorText = "";
			}
			GUI.backgroundColor = Color.red;
			GUI.contentColor = Color.white;
			if (GUILayout.Button("Discard", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
			{
				FastLinkPlugin.EditorText = "";
			}
			GUILayout.Space(20f);
			GUI.backgroundColor = Color.cyan;
			GUI.contentColor = Color.white;
			if (GUILayout.Button(FastLinkPlugin.RichTextOn ? "No Rich Text" : "Use Rich Text", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }))
			{
				FastLinkPlugin.RichTextOn = !FastLinkPlugin.RichTextOn;
			}
			GUILayout.EndVertical();
		}

		private static void DoQuickLoad(string fileName, FileSource fileSource)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			string @string = PlayerPrefs.GetString("world");
			Game.SetProfile(fileName, fileSource);
			if (string.IsNullOrEmpty(@string))
			{
				return;
			}
			FastLinkPlugin.FastLinkLogger.LogDebug((object)("got world name " + @string));
			FejdStartup.instance.UpdateCharacterList();
			FejdStartup.instance.UpdateWorldList(true);
			bool isOn = FejdStartup.instance.m_publicServerToggle.isOn;
			bool isOn2 = FejdStartup.instance.m_openServerToggle.isOn;
			string text = ((TMP_InputField)FejdStartup.instance.m_serverPassword).text;
			World val = FejdStartup.instance.FindWorld(@string);
			if (val != null)
			{
				FastLinkPlugin.FastLinkLogger.LogDebug((object)"got world");
				ZNet.SetServer(true, isOn2, isOn, @string, text, val);
				ZNet.ResetServerHost();
				FastLinkPlugin.FastLinkLogger.LogDebug((object)"Set server");
				try
				{
					string text2 = $"open:{isOn2},public:{isOn}";
					Gogan.LogEvent("Menu", "WorldStart", text2, 0L);
				}
				catch
				{
					FastLinkPlugin.FastLinkLogger.LogDebug((object)"Error calling Gogan... oh well");
				}
				FastLinkPlugin.FastLinkLogger.LogDebug((object)"transitioning...");
				FejdStartup.instance.TransitionToMainScene();
			}
		}
	}
}
namespace FastLink.Patches
{
	[HarmonyPatch(typeof(FejdStartup), "OnSelelectCharacterBack")]
	internal class PatchCharacterBack
	{
		private static void Postfix()
		{
			if (Object.op_Implicit((Object)(object)SetupGui.Fastlink))
			{
				Functions.AbortConnect();
			}
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "Start")]
	internal static class FejdStartupStartPatch
	{
		private static void Postfix(FejdStartup __instance)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			FastLinkPlugin.instance._harmony.Patch((MethodBase)(((int)ZNet.m_onlineBackend == 1) ? AccessTools.DeclaredMethod(typeof(ZPlayFabMatchmaking), "OnFailed", (Type[])null, (Type[])null) : AccessTools.DeclaredMethod(typeof(ZSteamMatchmaking), "OnPingFailed", (Type[])null, (Type[])null)), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(FejdStartupStartPatch), "Failed", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void Failed()
		{
			if (Object.op_Implicit((Object)(object)SetupGui.Fastlink))
			{
				JoinServerFailed();
			}
		}

		private static void JoinServerFailed()
		{
			FastLinkPlugin.FastLinkLogger.LogError((object)"Server connection failed");
			SetupGui.Connecting = null;
		}
	}
	[HarmonyPatch(typeof(ZNet), "RPC_ClientHandshake")]
	internal class PatchPasswordPrompt
	{
		private static bool Prefix(ZNet __instance, ZRpc rpc, bool needPassword, string serverPasswordSalt)
		{
			if (FastLinkPlugin.ShowPasswordPrompt.Value == FastLinkPlugin.Toggle.On)
			{
				return true;
			}
			string text = Functions.CurrentPass();
			if (string.IsNullOrEmpty(text))
			{
				return true;
			}
			ZNet.m_serverPasswordSalt = serverPasswordSalt;
			if (needPassword)
			{
				string text2 = text.Aggregate("", (string current, char characters) => current + "*");
				FastLinkPlugin.FastLinkLogger.LogDebug((object)("Authenticating with saved password...REDACTED: " + text2));
				((Component)__instance.m_connectingDialog).gameObject.SetActive(false);
				__instance.SendPeerInfo(rpc, text);
				return false;
			}
			FastLinkPlugin.FastLinkLogger.LogDebug((object)"Server didn't want password?");
			return true;
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "LoadMainScene")]
	internal static class FejdStartup_LoadMainScene_Patch
	{
		private static void Postfix(FejdStartup __instance)
		{
			if (SetupGui.Fastlink.activeSelf)
			{
				SetupGui.Fastlink.SetActive(false);
			}
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "SetupGui")]
	internal class SetupGui
	{
		public static GameObject Fastlink = null;

		public static GameObject FastlinkTooltip = null;

		public static GameObject FastlinkRootGo = null;

		public static readonly List<Definition> MServerList = new List<Definition>();

		public static Definition? MJoinServer = new Definition();

		public static readonly List<GameObject> MServerListElements = new List<GameObject>();

		public static TextMeshProUGUI? MServerCount;

		public static GameObject MServerListElement = new GameObject();

		public static float m_serverListElementStep = 28f;

		public static RectTransform MServerListRoot = new RectTransform();

		public static float MServerListBaseSize;

		public static Task<IPHostEntry>? ResolveTask;

		public static Definition? Connecting;

		private static void Postfix(FejdStartup __instance)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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)
			Connecting = null;
			foreach (GameObject mServerListElement in MServerListElements)
			{
				Object.DestroyImmediate((Object)(object)mServerListElement);
			}
			MServerListElements.Clear();
			Servers.Init();
			FastlinkRootGo = new GameObject("FastLink");
			FastlinkRootGo.AddComponent<RectTransform>();
			FastlinkRootGo.AddComponent<DragControl>();
			FastlinkRootGo.transform.SetParent(GameObject.Find("GuiRoot/GUI/StartGui").transform);
			Fastlink = Object.Instantiate<GameObject>(GameObject.Find("GUI/StartGui/StartGame/Panel/JoinPanel").gameObject, FastlinkRootGo.transform);
			Object.DestroyImmediate((Object)(object)Fastlink.gameObject.GetComponent<TabHandler>());
			Object.DestroyImmediate((Object)(object)Fastlink.gameObject.GetComponent<ServerListGui>());
			Object.DestroyImmediate((Object)(object)Fastlink.gameObject.GetComponent<UIGamePad>());
			Fastlink.transform.SetParent(FastlinkRootGo.transform);
			Fastlink.gameObject.transform.localScale = FastLinkPlugin.LocalScale.Value;
			FastlinkRootGo.transform.position = Vector2.op_Implicit(new Vector2(FastLinkPlugin.UIAnchor.Value.x, FastLinkPlugin.UIAnchor.Value.y));
			if (!Fastlink.activeSelf)
			{
				Fastlink.SetActive(true);
			}
			((Component)Fastlink.transform.Find("topic")).GetComponent<TMP_Text>().text = "Fast Link";
			FastlinkTooltip.gameObject.SetActive(false);
			try
			{
				Functions.DestroyAll(Fastlink);
			}
			catch (Exception arg)
			{
				FastLinkPlugin.FastLinkLogger.LogError((object)$"Problem in the destroying of things!{arg}");
				throw;
			}
			Functions.BuildPanelFocusChrome(Fastlink);
			Functions.UpdatePanelFocusChrome(focused: false);
			Functions.PopulateServerList(Fastlink);
			Functions.UpdateServerList();
			if (ZSteamMatchmaking.m_instance == null)
			{
				ZSteamMatchmaking.Initialize();
			}
		}
	}
	internal class Servers
	{
		internal static string ConfigFileName = "Azumatt.FastLink_servers.yml";

		public static string ConfigPath;

		public static List<Definition> entries;

		public static void Init()
		{
			entries.Clear();
			try
			{
				if (!File.Exists(ConfigPath))
				{
					using StreamWriter streamWriter = File.CreateText(ConfigPath);
					streamWriter.Write((object?)new StringBuilder().AppendLine("# Configure your servers for Azumatt's FastLink mod in this file.").AppendLine("# Servers are automatically sorted alphabetically when shown in the list.").AppendLine("# This file live updates the in-game listing. Feel free to change it while in the main menu.")
						.AppendLine("")
						.AppendLine("Example Server:")
						.AppendLine("  address: example.com")
						.AppendLine("  port: 1234")
						.AppendLine("  password: somepassword")
						.AppendLine("")
						.AppendLine("Some IPv6 Server:")
						.AppendLine("  address: 2606:2800:220:1:248:1893:25c8:1946")
						.AppendLine("  port: 4023")
						.AppendLine("  password: a password with spaces")
						.AppendLine("")
						.AppendLine("Passwordless IPv4 Server:")
						.AppendLine("  address: 93.184.216.34")
						.AppendLine("  port: 9999")
						.AppendLine("")
						.AppendLine("# You can optionally change the color of your server name. Does not work for the address and port. Also, can show PvP status.")
						.AppendLine("<color=red>Another IPv4 Server</color>:")
						.AppendLine("  address: 192.0.2.146")
						.AppendLine("  port: 9999")
						.AppendLine("  ispvp: true")
						.AppendLine("# You can specify if a server is crossplay or not. This will show the crossplay's \"Shuffle\" icon. Please note, this is not fully supported at this time.")
						.AppendLine("Crossplay Server:")
						.AppendLine("  address: 92.183.211.42")
						.AppendLine("  port: 9999")
						.AppendLine("  password: somepassword")
						.AppendLine("  iscrossplay: true")
						.AppendLine("  ispvp: true")
						.AppendLine("# You can specify if a server uses the whitelist for players or not. This will show in the tooltip only.")
						.AppendLine("Whitelisted Server:")
						.AppendLine("  address: 92.183.211.42")
						.AppendLine("  port: 9999")
						.AppendLine("  password: somepassword")
						.AppendLine("  iscrossplay: true")
						.AppendLine("  ispvp: true")
						.AppendLine("  iswhitelisted: true"));
					streamWriter.Close();
				}
				if (File.Exists(ConfigPath))
				{
					entries.AddRange(Definition.Parse(File.ReadAllText(ConfigPath)));
					FastLinkPlugin.FastLinkLogger.LogDebug((object)$"Loaded {entries.Count} server entries");
				}
			}
			catch (Exception arg)
			{
				FastLinkPlugin.FastLinkLogger.LogError((object)$"Error loading config {arg}");
			}
		}

		static Servers()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			ConfigPath = configPath + directorySeparatorChar + ConfigFileName;
			entries = new List<Definition>();
		}
	}
}
namespace FastLink.Net
{
	internal static class ServerStatusService
	{
		internal delegate void RowApplyCallback(int index, Definition def, ServerListEntryData entry);

		private struct Cached
		{
			public ServerListEntryData Entry;

			public DateTime WhenUtc;
		}

		private sealed class WorkItem
		{
			public readonly Definition Def;

			public readonly int Index;

			public readonly uint[] IpCandidates;

			public readonly ushort[] PortCandidates;

			public int Attempt;

			public string CacheKey => $"{Def.address}:{Def.port}";

			public WorkItem(Definition def, int index, uint[] ips, ushort[] ports)
			{
				Def = def;
				Index = index;
				IpCandidates = ips;
				PortCandidates = ports;
				Attempt = 0;
			}

			public bool TryCurrent(out uint ip, out ushort qport, out int ipIdx, out int portIdx)
			{
				ipIdx = Attempt % IpCandidates.Length;
				portIdx = Attempt / IpCandidates.Length;
				if (IpCandidates.Length == 0 || portIdx >= PortCandidates.Length)
				{
					ip = 0u;
					qport = 0;
					return false;
				}
				ip = IpCandidates[ipIdx];
				qport = PortCandidates[portIdx];
				return true;
			}

			public bool Advance()
			{
				Attempt++;
				int num = IpCandidates.Length * PortCandidates.Length;
				return Attempt < num;
			}
		}

		private static readonly TimeSpan TTL = TimeSpan.FromSeconds(10.0);

		private static readonly Dictionary<string, Cached> _cache = new Dictionary<string, Cached>();

		private static readonly Queue<WorkItem> _queue = new Queue<WorkItem>();

		private static WorkItem? _active;

		private static HServerQuery _activeQuery = HServerQuery.Invalid;

		private static readonly ISteamMatchmakingPingResponse _pingHandler = new ISteamMatchmakingPingResponse(new ServerResponded(OnPingRespond), new ServerFailedToRespond(OnPingFailed));

		private static RowApplyCallback _apply;

		internal static void RequestStatus(Definition def, int index, RowApplyCallback apply)
		{
			//IL_0083: 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)
			_apply = apply ?? throw new ArgumentNullException("apply");
			string key = $"{def.address}:{def.port}";
			if (_cache.TryGetValue(key, out var value) && DateTime.UtcNow - value.WhenUtc < TTL)
			{
				_apply(index, def, value.Entry);
				return;
			}
			if (!ResolveIPv4Both(def.address, out var hostOrder, out var networkOrder))
			{
				StoreAndApply(index, def, BuildUnavailable(def));
				return;
			}
			ushort[] ports = new List<ushort>
			{
				(ushort)((uint)(def.port + 1) & 0xFFFFu),
				27016,
				27015,
				def.port
			}.Distinct().ToArray();
			uint[] ips = ((hostOrder == networkOrder) ? new uint[1] { hostOrder } : new uint[2] { hostOrder, networkOrder });
			_queue.Enqueue(new WorkItem(def, index, ips, ports));
			Pump();
		}

		internal static void RefreshAll(IReadOnlyList<Definition> defs, RowApplyCallback apply)
		{
			_apply = apply ?? throw new ArgumentNullException("apply");
			while (_queue.Count > 0)
			{
				_queue.Dequeue();
			}
			TryCancelActive();
			foreach (Definition def in defs)
			{
				RequestStatus(def, -1, apply);
			}
		}

		private static void Pump()
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			if (_active == null && _queue.Count != 0)
			{
				_active = _queue.Dequeue();
				if (!_active.TryCurrent(out var ip, out var qport, out var ipIdx, out var portIdx))
				{
					FailActiveAndFinish();
					return;
				}
				FastLinkPlugin.FastLinkLogger.LogDebug((object)$"[Status] Pinging {_active.Def.address}:{qport} (game port {_active.Def.port}) [ip#{ipIdx},port#{portIdx}]");
				_activeQuery = SteamMatchmakingServers.PingServer(ip, qport, _pingHandler);
			}
		}

		private static void OnPingRespond(gameserveritem_t data)
		{
			//IL_0072: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			FastLinkPlugin.FastLinkLogger.LogDebug((object)$"[Status] Responded {data.GetServerName()} players {data.m_nPlayers}/{data.m_nMaxPlayers} {data.m_bPassword} {data.GetGameDescription()} {data.GetGameDir()}");
			if (_active != null)
			{
				ServerListEntryData entry = BuildEntryFromPing(data, _active.Def);
				Store(entry, _active.CacheKey);
				_apply?.Invoke(_active.Index, _active.Def, entry);
				FinishPing();
			}
		}

		private static void OnPingFailed()
		{
			//IL_002f: 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)
			FastLinkPlugin.FastLinkLogger.LogDebug((object)"[Status] Ping FAILED");
			if (_active != null)
			{
				if (_active.Advance())
				{
					WorkItem active = _active;
					_active = null;
					_activeQuery = HServerQuery.Invalid;
					_queue.Enqueue(active);
					Pump();
				}
				else
				{
					FailActiveAndFinish();
				}
			}
		}

		private static void FailActiveAndFinish()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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)
			ServerListEntryData entry = BuildUnavailable(_active.Def);
			Store(entry, _active.CacheKey);
			_apply?.Invoke(_active.Index, _active.Def, entry);
			FinishPing();
		}

		private static void FinishPing()
		{
			//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)
			_active = null;
			_activeQuery = HServerQuery.Invalid;
			if (_queue.Count > 0)
			{
				Pump();
			}
		}

		private static void TryCancelActive()
		{
			//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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (_activeQuery != HServerQuery.Invalid)
			{
				SteamMatchmakingServers.CancelServerQuery(_activeQuery);
			}
			_activeQuery = HServerQuery.Invalid;
			_active = null;
		}

		private static void StoreAndApply(int index, Definition def, ServerListEntryData entry)
		{
			//IL_0000: 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)
			Store(entry, $"{def.address}:{def.port}");
			_apply?.Invoke(index, def, entry);
		}

		private static void Store(ServerListEntryData entry, string key)
		{
			//IL_0010: 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)
			_cache[key] = new Cached
			{
				Entry = entry,
				WhenUtc = DateTime.UtcNow
			};
		}

		private static ServerListEntryData BuildUnavailable(Definition def)
		{
			//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_001f: Unknown result type (might be due to invalid IL or missing references)
			ServerMatchmakingData val = default(ServerMatchmakingData);
			((ServerMatchmakingData)(ref val))..ctor(DateTime.UtcNow, true);
			return new ServerListEntryData(new ServerData(BuildJoinData(def), val), def.serverName);
		}

		private static ServerListEntryData BuildEntryFromPing(gameserveritem_t i, Definition def)
		{
			//IL_0013: 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_0054: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			GameVersion val = default(GameVersion);
			uint num = default(uint);
			string[] array = default(string[]);
			ZSteamMatchmaking.DecodeTags(i.GetGameTags(), ref val, ref num, ref array);
			SteamNetworkingIPAddr val2 = default(SteamNetworkingIPAddr);
			((SteamNetworkingIPAddr)(ref val2)).SetIPv4(((servernetadr_t)(ref i.m_NetAdr)).GetIP(), ((servernetadr_t)(ref i.m_NetAdr)).GetConnectionPort());
			ServerMatchmakingData val3 = default(ServerMatchmakingData);
			((ServerMatchmakingData)(ref val3))..ctor(DateTime.UtcNow, i.GetServerName(), (uint)i.m_nPlayers, (uint)i.m_nMaxPlayers, PlatformUserID.None, val, num, (string)null, i.m_bPassword, new Platform("Steam"), array);
			return new ServerListEntryData(new ServerData(new ServerJoinData(new ServerJoinDataDedicated(((SteamNetworkingIPAddr)(ref val2)).GetIPv4(), val2.m_port)), val3), def.serverName);
		}

		private static ServerJoinData BuildJoinData(Definition def)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!ResolveIPv4Both(def.address, out var hostOrder, out var _))
			{
				hostOrder = 0u;
			}
			SteamNetworkingIPAddr val = default(SteamNetworkingIPAddr);
			((SteamNetworkingIPAddr)(ref val)).SetIPv4(hostOrder, def.port);
			return new ServerJoinData(new ServerJoinDataDedicated(((SteamNetworkingIPAddr)(ref val)).GetIPv4(), val.m_port));
		}

		private static bool ResolveIPv4Both(string host, out uint hostOrder, out uint networkOrder)
		{
			hostOrder = 0u;
			networkOrder = 0u;
			try
			{
				IPAddress iPAddress = null;
				if (ZSteamMatchmaking.m_instance != null)
				{
					IPAddress iPAddress2 = ZSteamMatchmaking.instance.FindIP(host);
					if (iPAddress2 != null && iPAddress2.AddressFamily == AddressFamily.InterNetwork)
					{
						iPAddress = iPAddress2;
					}
				}
				if (iPAddress == null)
				{
					IPAddress[] addressList = Dns.GetHostEntry(host).AddressList;
					foreach (IPAddress iPAddress3 in addressList)
					{
						if (iPAddress3.AddressFamily == AddressFamily.InterNetwork)
						{
							iPAddress = iPAddress3;
							break;
						}
					}
				}
				if (iPAddress == null)
				{
					return false;
				}
				byte[] addressBytes = iPAddress.GetAddressBytes();
				hostOrder = (uint)(addressBytes[0] | (addressBytes[1] << 8) | (addressBytes[2] << 16) | (addressBytes[3] << 24));
				networkOrder = (uint)IPAddress.HostToNetworkOrder(BitConverter.ToInt32(addressBytes, 0));
				return true;
			}
			catch (Exception arg)
			{
				FastLinkPlugin.FastLinkLogger.LogDebug((object)$"ResolveIPv4Both failed for {host}: {arg}");
				return false;
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 YamlDotNet
{
	internal sealed class CultureInfoAdapter : CultureInfo
	{
		private readonly IFormatProvider provider;

		public CultureInfoAdapter(CultureInfo baseCulture, IFormatProvider provider)
			: base(baseCulture.Name)
		{
			this.provider = provider;
		}

		public override object? GetFormat(Type formatType)
		{
			return provider.GetFormat(formatType);
		}
	}
	internal static class Polyfills
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static bool Contains(this string source, char c)
		{
			return source.IndexOf(c) != -1;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static bool EndsWith(this string source, char c)
		{
			if (source.Length > 0)
			{
				return source[source.Length - 1] == c;
			}
			return false;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static bool StartsWith(this string source, char c)
		{
			if (source.Length > 0)
			{
				return source[0] == c;
			}
			return false;
		}
	}
	internal static class PropertyInfoExtensions
	{
		public static object? ReadValue(this PropertyInfo property, object target)
		{
			return property.GetValue(target, null);
		}
	}
	internal static class ReflectionExtensions
	{
		private static readonly Func<PropertyInfo, bool> IsInstance = (PropertyInfo property) => !(property.GetMethod ?? property.SetMethod).IsStatic;

		private static readonly Func<PropertyInfo, bool> IsInstancePublic = (PropertyInfo property) => IsInstance(property) && (property.GetMethod ?? property.SetMethod).IsPublic;

		public static Type? BaseType(this Type type)
		{
			return type.GetTypeInfo().BaseType;
		}

		public static bool IsValueType(this Type type)
		{
			return type.GetTypeInfo().IsValueType;
		}

		public static bool IsGenericType(this Type type)
		{
			return type.GetTypeInfo().IsGenericType;
		}

		public static bool IsGenericTypeDefinition(this Type type)
		{
			return type.GetTypeInfo().IsGenericTypeDefinition;
		}

		public static Type? GetImplementationOfOpenGenericInterface(this Type type, Type openGenericType)
		{
			if (!openGenericType.IsGenericType || !openGenericType.IsInterface)
			{
				throw new ArgumentException("The type must be a generic type definition and an interface", "openGenericType");
			}
			if (IsGenericDefinitionOfType(type, openGenericType))
			{
				return type;
			}
			return type.FindInterfaces((Type t, object context) => IsGenericDefinitionOfType(t, context), openGenericType).FirstOrDefault();
			static bool IsGenericDefinitionOfType(Type t, object? context)
			{
				if (t.IsGenericType)
				{
					return t.GetGenericTypeDefinition() == (Type)context;
				}
				return false;
			}
		}

		public static bool IsInterface(this Type type)
		{
			return type.GetTypeInfo().IsInterface;
		}

		public static bool IsEnum(this Type type)
		{
			return type.GetTypeInfo().IsEnum;
		}

		public static bool IsRequired(this MemberInfo member)
		{
			return member.GetCustomAttributes(inherit: true).Any((object x) => x.GetType().FullName == "System.Runtime.CompilerServices.RequiredMemberAttribute");
		}

		public static bool HasDefaultConstructor(this Type type, bool allowPrivateConstructors)
		{
			BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public;
			if (allowPrivateConstructors)
			{
				bindingFlags |= BindingFlags.NonPublic;
			}
			if (!type.IsValueType)
			{
				return type.GetConstructor(bindingFlags, null, Type.EmptyTypes, null) != null;
			}
			return true;
		}

		public static bool IsAssignableFrom(this Type type, Type source)
		{
			return type.IsAssignableFrom(source.GetTypeInfo());
		}

		public static bool IsAssignableFrom(this Type type, TypeInfo source)
		{
			return type.GetTypeInfo().IsAssignableFrom(source);
		}

		public static TypeCode GetTypeCode(this Type type)
		{
			if (type.IsEnum())
			{
				type = Enum.GetUnderlyingType(type);
			}
			if (type == typeof(bool))
			{
				return TypeCode.Boolean;
			}
			if (type == typeof(char))
			{
				return TypeCode.Char;
			}
			if (type == typeof(sbyte))
			{
				return TypeCode.SByte;
			}
			if (type == typeof(byte))
			{
				return TypeCode.Byte;
			}
			if (type == typeof(short))
			{
				return TypeCode.Int16;
			}
			if (type == typeof(ushort))
			{
				return TypeCode.UInt16;
			}
			if (type == typeof(int))
			{
				return TypeCode.Int32;
			}
			if (type == typeof(uint))
			{
				return TypeCode.UInt32;
			}
			if (type == typeof(long))
			{
				return TypeCode.Int64;
			}
			if (type == typeof(ulong))
			{
				return TypeCode.UInt64;
			}
			if (type == typeof(float))
			{
				return TypeCode.Single;
			}
			if (type == typeof(double))
			{
				return TypeCode.Double;
			}
			if (type == typeof(decimal))
			{
				return TypeCode.Decimal;
			}
			if (type == typeof(DateTime))
			{
				return TypeCode.DateTime;
			}
			if (type == typeof(string))
			{
				return TypeCode.String;
			}
			return TypeCode.Object;
		}

		public static bool IsDbNull(this object value)
		{
			return value?.GetType()?.FullName == "System.DBNull";
		}

		public static Type[] GetGenericArguments(this Type type)
		{
			return type.GetTypeInfo().GenericTypeArguments;
		}

		public static PropertyInfo? GetPublicProperty(this Type type, string name)
		{
			string name2 = name;
			return type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public).FirstOrDefault((PropertyInfo p) => p.Name == name2);
		}

		public static FieldInfo? GetPublicStaticField(this Type type, string name)
		{
			return type.GetRuntimeField(name);
		}

		public static IEnumerable<PropertyInfo> GetProperties(this Type type, bool includeNonPublic)
		{
			Func<PropertyInfo, bool> predicate = (includeNonPublic ? IsInstance : IsInstancePublic);
			if (!type.IsInterface())
			{
				return type.GetRuntimeProperties().Where(predicate);
			}
			return new Type[1] { type }.Concat(type.GetInterfaces()).SelectMany((Type i) => i.GetRuntimeProperties().Where(predicate));
		}

		public static IEnumerable<PropertyInfo> GetPublicProperties(this Type type)
		{
			return type.GetProperties(includeNonPublic: false);
		}

		public static IEnumerable<FieldInfo> GetPublicFields(this Type type)
		{
			return from f in type.GetRuntimeFields()
				where !f.IsStatic && f.IsPublic
				select f;
		}

		public static IEnumerable<MethodInfo> GetPublicStaticMethods(this Type type)
		{
			return from m in type.GetRuntimeMethods()
				where m.IsPublic && m.IsStatic
				select m;
		}

		public static MethodInfo GetPrivateStaticMethod(this Type type, string name)
		{
			string name2 = name;
			return type.GetRuntimeMethods().FirstOrDefault((MethodInfo m) => !m.IsPublic && m.IsStatic && m.Name.Equals(name2)) ?? throw new MissingMethodException("Expected to find a method named '" + name2 + "' in '" + type.FullName + "'.");
		}

		public static MethodInfo? GetPublicStaticMethod(this Type type, string name, params Type[] parameterTypes)
		{
			string name2 = name;
			Type[] parameterTypes2 = parameterTypes;
			return type.GetRuntimeMethods().FirstOrDefault(delegate(MethodInfo m)
			{
				if (m.IsPublic && m.IsStatic && m.Name.Equals(name2))
				{
					ParameterInfo[] parameters = m.GetParameters();
					if (parameters.Length == parameterTypes2.Length)
					{
						return parameters.Zip(parameterTypes2, (ParameterInfo pi, Type pt) => pi.ParameterType == pt).All((bool r) => r);
					}
					return false;
				}
				return false;
			});
		}

		public static MethodInfo? GetPublicInstanceMethod(this Type type, string name)
		{
			string name2 = name;
			return type.GetRuntimeMethods().FirstOrDefault((MethodInfo m) => m.IsPublic && !m.IsStatic && m.Name.Equals(name2));
		}

		public static MethodInfo? GetGetMethod(this PropertyInfo property, bool nonPublic)
		{
			MethodInfo methodInfo = property.GetMethod;
			if (!nonPublic && !methodInfo.IsPublic)
			{
				methodInfo = null;
			}
			return methodInfo;
		}

		public static MethodInfo? GetSetMethod(this PropertyInfo property)
		{
			return property.SetMethod;
		}

		public static IEnumerable<Type> GetInterfaces(this Type type)
		{
			return type.GetTypeInfo().ImplementedInterfaces;
		}

		public static bool IsInstanceOf(this Type type, object o)
		{
			if (!(o.GetType() == type))
			{
				return o.GetType().GetTypeInfo().IsSubclassOf(type);
			}
			return true;
		}

		public static Attribute[] GetAllCustomAttributes<TAttribute>(this PropertyInfo member)
		{
			return Attribute.GetCustomAttributes(member, typeof(TAttribute), inherit: true);
		}

		public static bool AcceptsNull(this MemberInfo member)
		{
			object[] customAttributes = member.DeclaringType.GetCustomAttributes(inherit: true);
			object obj = customAttributes.FirstOrDefault((object x) => x.GetType().FullName == "System.Runtime.CompilerServices.NullableContextAttribute");
			int num = 0;
			if (obj != null)
			{
				Type type = obj.GetType();
				PropertyInfo property = type.GetProperty("Flag");
				num = (byte)property.GetValue(obj);
			}
			object[] customAttributes2 = member.GetCustomAttributes(inherit: true);
			object obj2 = customAttributes2.FirstOrDefault((object x) => x.GetType().FullName == "System.Runtime.CompilerServices.NullableAttribute");
			PropertyInfo propertyInfo = (obj2?.GetType())?.GetProperty("NullableFlags");
			byte[] source = (byte[])propertyInfo.GetValue(obj2);
			return source.Any((byte x) => x == 2) || num == 2;
		}
	}
	internal static class StandardRegexOptions
	{
		public const RegexOptions Compiled = RegexOptions.Compiled;
	}
}
namespace YamlDotNet.Serialization
{
	internal abstract class BuilderSkeleton<TBuilder> where TBuilder : BuilderSkeleton<TBuilder>
	{
		internal INamingConvention namingConvention = NullNamingConvention.Instance;

		internal INamingConvention enumNamingConvention = NullNamingConvention.Instance;

		internal ITypeResolver typeResolver;

		internal readonly YamlAttributeOverrides overrides;

		internal readonly LazyComponentRegistrationList<Nothing, IYamlTypeConverter> typeConverterFactories;

		internal readonly LazyComponentRegistrationList<ITypeInspector, ITypeInspector> typeInspectorFactories;

		internal bool ignoreFields;

		internal bool includeNonPublicProperties;

		internal Settings settings;

		internal YamlFormatter yamlFormatter = YamlFormatter.Default;

		protected abstract TBuilder Self { get; }

		internal BuilderSkeleton(ITypeResolver typeResolver)
		{
			overrides = new YamlAttributeOverrides();
			typeConverterFactories = new LazyComponentRegistrationList<Nothing, IYamlTypeConverter>
			{
				{
					typeof(YamlDotNet.Serialization.Converters.GuidConverter),
					(Nothing _) => new YamlDotNet.Serialization.Converters.GuidConverter(jsonCompatible: false)
				},
				{
					typeof(SystemTypeConverter),
					(Nothing _) => new SystemTypeConverter()
				}
			};
			typeInspectorFactories = new LazyComponentRegistrationList<ITypeInspector, ITypeInspector>();
			this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver");
			settings = new Settings();
		}

		public TBuilder IgnoreFields()
		{
			ignoreFields = true;
			return Self;
		}

		public TBuilder IncludeNonPublicProperties()
		{
			includeNonPublicProperties = true;
			return Self;
		}

		public TBuilder EnablePrivateConstructors()
		{
			settings.AllowPrivateConstructors = true;
			return Self;
		}

		public TBuilder WithNamingConvention(INamingConvention namingConvention)
		{
			this.namingConvention = namingConvention ?? throw new ArgumentNullException("namingConvention");
			return Self;
		}

		public TBuilder WithEnumNamingConvention(INamingConvention enumNamingConvention)
		{
			this.enumNamingConvention = enumNamingConvention;
			return Self;
		}

		public TBuilder WithTypeResolver(ITypeResolver typeResolver)
		{
			this.typeResolver = typeResolver ?? throw new ArgumentNullException("typeResolver");
			return Self;
		}

		public abstract TBuilder WithTagMapping(TagName tag, Type type);

		public TBuilder WithAttributeOverride<TClass>(Expression<Func<TClass, object>> propertyAccessor, Attribute attribute)
		{
			overrides.Add(propertyAccessor, attribute);
			return Self;
		}

		public TBuilder WithAttributeOverride(Type type, string member, Attribute attribute)
		{
			overrides.Add(type, member, attribute);
			return Self;
		}

		public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter)
		{
			return WithTypeConverter(typeConverter, delegate(IRegistrationLocationSelectionSyntax<IYamlTypeConverter> w)
			{
				w.OnTop();
			});
		}

		public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter, Action<IRegistrationLocationSelectionSyntax<IYamlTypeConverter>> where)
		{
			IYamlTypeConverter typeConverter2 = typeConverter;
			if (typeConverter2 == null)
			{
				throw new ArgumentNullException("typeConverter");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeConverterFactories.CreateRegistrationLocationSelector(typeConverter2.GetType(), (Nothing _) => typeConverter2));
			return Self;
		}

		public TBuilder WithTypeConverter<TYamlTypeConverter>(WrapperFactory<IYamlTypeConverter, IYamlTypeConverter> typeConverterFactory, Action<ITrackingRegistrationLocationSelectionSyntax<IYamlTypeConverter>> where) where TYamlTypeConverter : IYamlTypeConverter
		{
			WrapperFactory<IYamlTypeConverter, IYamlTypeConverter> typeConverterFactory2 = typeConverterFactory;
			if (typeConverterFactory2 == null)
			{
				throw new ArgumentNullException("typeConverterFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeConverterFactories.CreateTrackingRegistrationLocationSelector(typeof(TYamlTypeConverter), (IYamlTypeConverter wrapped, Nothing _) => typeConverterFactory2(wrapped)));
			return Self;
		}

		public TBuilder WithoutTypeConverter<TYamlTypeConverter>() where TYamlTypeConverter : IYamlTypeConverter
		{
			return WithoutTypeConverter(typeof(TYamlTypeConverter));
		}

		public TBuilder WithoutTypeConverter(Type converterType)
		{
			if (converterType == null)
			{
				throw new ArgumentNullException("converterType");
			}
			typeConverterFactories.Remove(converterType);
			return Self;
		}

		public TBuilder WithTypeInspector<TTypeInspector>(Func<ITypeInspector, TTypeInspector> typeInspectorFactory) where TTypeInspector : ITypeInspector
		{
			return WithTypeInspector(typeInspectorFactory, delegate(IRegistrationLocationSelectionSyntax<ITypeInspector> w)
			{
				w.OnTop();
			});
		}

		public TBuilder WithTypeInspector<TTypeInspector>(Func<ITypeInspector, TTypeInspector> typeInspectorFactory, Action<IRegistrationLocationSelectionSyntax<ITypeInspector>> where) where TTypeInspector : ITypeInspector
		{
			Func<ITypeInspector, TTypeInspector> typeInspectorFactory2 = typeInspectorFactory;
			if (typeInspectorFactory2 == null)
			{
				throw new ArgumentNullException("typeInspectorFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeInspectorFactories.CreateRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector inner) => typeInspectorFactory2(inner)));
			return Self;
		}

		public TBuilder WithTypeInspector<TTypeInspector>(WrapperFactory<ITypeInspector, ITypeInspector, TTypeInspector> typeInspectorFactory, Action<ITrackingRegistrationLocationSelectionSyntax<ITypeInspector>> where) where TTypeInspector : ITypeInspector
		{
			WrapperFactory<ITypeInspector, ITypeInspector, TTypeInspector> typeInspectorFactory2 = typeInspectorFactory;
			if (typeInspectorFactory2 == null)
			{
				throw new ArgumentNullException("typeInspectorFactory");
			}
			if (where == null)
			{
				throw new ArgumentNullException("where");
			}
			where(typeInspectorFactories.CreateTrackingRegistrationLocationSelector(typeof(TTypeInspector), (ITypeInspector wrapped, ITypeInspector inner) => typeInspectorFactory2(wrapped, inner)));
			return Self;
		}

		public TBuilder WithoutTypeInspector<TTypeInspector>() where TTypeInspector : ITypeInspector
		{
			return WithoutTypeInspector(typeof(TTypeInspector));
		}

		public TBuilder WithoutTypeInspector(Type inspectorType)
		{
			if (inspectorType == null)
			{
				throw new ArgumentNullException("inspectorType");
			}
			typeInspectorFactories.Remove(inspectorType);
			return Self;
		}

		public TBuilder WithYamlFormatter(YamlFormatter formatter)
		{
			yamlFormatter = formatter ?? throw new ArgumentNullException("formatter");
			return Self;
		}

		protected IEnumerable<IYamlTypeConverter> BuildTypeConverters()
		{
			return typeConverterFactories.BuildComponentList();
		}
	}
	internal delegate TComponent WrapperFactory<TComponentBase, TComponent>(TComponentBase wrapped) where TComponent : TComponentBase;
	internal delegate TComponent WrapperFactory<TArgument, TComponentBase, TComponent>(TComponentBase wrapped, TArgument argument) where TComponent : TComponentBase;
	[Flags]
	internal enum DefaultValuesHandling
	{
		Preserve = 0,
		OmitNull = 1,
		OmitDefaults = 2,
		OmitEmptyCollections = 4
	}
	internal sealed class Deserializer : IDeserializer
	{
		private readonly IValueDeserializer valueDeserializer;

		public Deserializer()
			: this(new DeserializerBuilder().BuildValueDeserializer())
		{
		}

		private Deserializer(IValueDeserializer valueDeserializer)
		{
			this.valueDeserializer = valueDeserializer ?? throw new ArgumentNullException("valueDeserializer");
		}

		public static Deserializer FromValueDeserializer(IValueDeserializer valueDeserializer)
		{
			return new Deserializer(valueDeserializer);
		}

		public T Deserialize<T>(string input)
		{
			using StringReader input2 = new StringReader(input);
			return Deserialize<T>(input2);
		}

		public T Deserialize<T>(TextReader input)
		{
			return Deserialize<T>(new Parser(input));
		}

		public T Deserialize<T>(IParser parser)
		{
			return (T)Deserialize(parser, typeof(T));
		}

		public object? Deserialize(string input)
		{
			return Deserialize<object>(input);
		}

		public object? Deserialize(TextReader input)
		{
			return Deserialize<object>(input);
		}

		public object? Deserialize(IParser parser)
		{
			return Deserialize<object>(parser);
		}

		public object? Deserialize(string input, Type type)
		{
			using StringReader input2 = new StringReader(input);
			return Deserialize(input2, type);
		}

		public object? Deserialize(TextReader input, Type type)
		{
			return Deserialize(new Parser(input), type);
		}

		public object? Deserialize(IParser parser, Type type)
		{
			if (parser == null)
			{
				throw new ArgumentNullException("parser");
			}
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			YamlDotNet.Core.Events.StreamStart @event;
			bool flag = parser.TryConsume<YamlDotNet.Core.Events.StreamStart>(out @event);
			YamlDotNet.Core.Events.DocumentStart event2;
			bool flag2 = parser.TryConsume<YamlDotNet.Core.Events.DocumentStart>(out event2);
			object result = null;
			if (!parser.Accept<YamlDotNet.Core.Events.DocumentEnd>(out var _) && !parser.Accept<YamlDotNet.Core.Events.StreamEnd>(out var _))
			{
				using SerializerState serializerState = new SerializerState();
				result = valueDeserializer.DeserializeValue(parser, type, serializerState, valueDeserializer);
				serializerState.OnDeserialization();
			}
			if (flag2)
			{
				parser.Consume<YamlDotNet.Core.Events.DocumentEnd>();
			}
			if (flag)
			{
				parser.Consume<YamlDotNet.Core.Events.StreamEnd>();
			}
			return result;
		}
	}
	internal sealed class DeserializerBuilder : BuilderSkeleton<DeserializerBuilder>
	{
		private Lazy<IObjectFactory> objectFactory;

		private readonly LazyComponentRegistrationList<Nothing, INodeDeserializer> nodeDeserializerFactories;

		private readonly LazyComponentRegistrationList<Nothing, INodeTypeResolver> nodeTypeResolverFactories;

		private readonly Dictionary<TagName, Type> tagMappings;

		private readonly Dictionary<Type, Type> typeMappings;

		private readonly ITypeConverter typeConverter;

		private bool ignoreUnmatched;

		private bool duplicateKeyChecking;

		private bool attemptUnknownTypeDeserialization;

		private bool enforceNullability;

		private bool caseInsensitivePropertyMatching;

		private bool enforceRequiredProperties;

		protected override DeserializerBuilder Self => this;

		public DeserializerBuilder()
			: base((ITypeResolver)new StaticTypeResolver())
		{
			typeMappings = new Dictionary<Type, Type>();
			objectFactory = new Lazy<IObjectFactory>(() => new DefaultObjectFactory(typeMappings, settings), isThreadSafe: true);
			tagMappings = new Dictionary<TagName, Type>
			{
				{
					FailsafeSchema.Tags.Map,
					typeof(Dictionary<object, object>)
				},
				{
					FailsafeSchema.Tags.Str,
					typeof(string)
				},
				{
					JsonSchema.Tags.Bool,
					typeof(bool)
				},
				{
					JsonSchema.Tags.Float,
					typeof(double)
				},
				{
					JsonSchema.Tags.Int,
					typeof(int)
				},
				{
					DefaultSchema.Tags.Timestamp,
					typeof(DateTime)
				}
			};
			typeInspectorFactories.Add(typeof(CachedTypeInspector), (ITypeInspector inner) => new CachedTypeInspector(inner));
			typeInspectorFactories.Add(typeof(NamingConventionTypeInspector), (ITypeInspector inner) => (!(namingConvention is NullNamingConvention)) ? new NamingConventionTypeInspector(inner, namingConvention) : inner);
			typeInspectorFactories.Add(typeof(YamlAttributesTypeInspector), (ITypeInspector inner) => new YamlAttributesTypeInspector(inner));
			typeInspectorFactories.Add(typeof(YamlAttributeOverridesInspector), (ITypeInspector inner) => (overrides == null) ? inner : new YamlAttributeOverridesInspector(inner, overrides.Clone()));
			typeInspectorFactories.Add(typeof(ReadableAndWritablePropertiesTypeInspector), (ITypeInspector inner) => new ReadableAndWritablePropertiesTypeInspector(inner));
			nodeDeserializerFactories = new LazyComponentRegistrationList<Nothing, INodeDeserializer>
			{
				{
					typeof(YamlConvertibleNodeDeserializer),
					(Nothing _) => new YamlConvertibleNodeDeserializer(objectFactory.Value)
				},
				{
					typeof(YamlSerializableNodeDeserializer),
					(Nothing _) => new YamlSerializableNodeDeserializer(objectFactory.Value)
				},
				{
					typeof(TypeConverterNodeDeserializer),
					(Nothing _) => new TypeConverterNodeDeserializer(BuildTypeConverters())
				},
				{
					typeof(NullNodeDeserializer),
					(Nothing _) => new NullNodeDeserializer()
				},
				{
					typeof(ScalarNodeDeserializer),
					(Nothing _) => new ScalarNodeDeserializer(attemptUnknownTypeDeserialization, typeConverter, BuildTypeInspector(), yamlFormatter, enumNamingConvention)
				},
				{
					typeof(ArrayNodeDeserializer),
					(Nothing _) => new ArrayNodeDeserializer(enumNamingConvention, BuildTypeInspector())
				},
				{
					typeof(DictionaryNodeDeserializer),
					(Nothing _) => new DictionaryNodeDeserializer(objectFactory.Value, duplicateKeyChecking)
				},
				{
					typeof(CollectionNodeDeserializer),
					(Nothing _) => new CollectionNodeDeserializer(objectFactory.Value, enumNamingConvention, BuildTypeInspector())
				},
				{
					typeof(EnumerableNodeDeserializer),
					(Nothing _) => new EnumerableNodeDeserializer()
				},
				{
					typeof(ObjectNodeDeserializer),
					(Nothing _) => new ObjectNodeDeserializer(objectFactory.Value, BuildTypeInspector(), ignoreUnmatched, duplicateKeyChecking, typeConverter, enumNamingConvention, enforceNullability, caseInsensitivePropertyMatching, enforceRequiredProperties, BuildTypeConverters())
				},
				{
					typeof(FsharpListNodeDeserializer),
					(Nothing _) => new FsharpListNodeDeserializer(BuildTypeInspector(), enumNamingConvention)
				}
			};
			nodeTypeResolverFactories = new LazyComponentRegistrationList<Nothing, INodeTypeResolver>
			{
				{
					typeof(MappingNodeTypeResolver),
					(Nothing _) => new MappingNodeTypeResolver(typeMappings)
				},
				{
					typeof(YamlConvertibleTypeResolver),
					(Nothing _) => new YamlConvertibleTypeResolver()
				},
				{
					typeof(YamlSerializableTypeResolver),
					(Nothing _) => new YamlSerializableTypeResolver()
				},
				{
					typeof(TagNodeTypeResolver),
					(Nothing _) => new TagNodeTypeResolver(tagMappings)
				},
				{
					typeof(PreventUnknownTagsNodeTypeResolver),
					(Nothing _) => new PreventUnknownTagsNodeTypeResolver()
				},
				{
					typeof(DefaultContainersNodeTypeResolver),
					(Nothing _) => new DefaultContainersNodeTypeResolver()
				}
			};
			typeConverter = new ReflectionTypeConverter();
		}

		public ITypeInspector BuildTypeInspector()
		{
			ITypeInspector typeInspector = new WritablePropertiesTypeInspector(typeResolver, includeNonPublicProperties);
			if (!ignoreFields)
			{
				typeInspector = new CompositeTypeInspector(new ReadableFieldsTypeInspector(typeResolver), typeInspector);
			}
			return typeInspectorFactories.BuildComponentChain(typeInspector);
		}

		public DeserializerBuilder WithAttemptingUnquotedStringTypeDeserialization()
		{
			attemptUnknownTypeDeserialization = true;
			return this;
		}

		public DeserializerBuilder WithObjectFactory(IObjectFactory objectFactory)
		{
			IObjectFactory objectFactory2 = objectFactory;
			if (objectFactory2 == null)
			{
				throw new ArgumentNullException("objectFactory");
			}
			this.objectFactory = new Lazy<IObjectFactory>(() => objectFactory2, isThreadSafe: true);
			retur