Decompiled source of BifrostGateway v1.0.1

BifrostGateway.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BifrostGateway
{
	[BepInPlugin("com.dfg.bifrostgateway", "Bifrost Gateway", "1.0.1")]
	[BepInProcess("valheim.exe")]
	public class BifrostGatewayPlugin : BaseUnityPlugin
	{
		public const string Guid = "com.dfg.bifrostgateway";

		public const string Version = "1.0.1";

		internal static ManualLogSource Log;

		private readonly List<GatewayServer> _servers = new List<GatewayServer>();

		private bool _loaded;

		internal static BifrostGatewayPlugin Instance { get; private set; }

		internal GatewaySettings Settings { get; private set; }

		private void Awake()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Settings = new GatewaySettings(((BaseUnityPlugin)this).Config);
			_servers.AddRange(GatewayStore.Load(out var warning));
			_loaded = true;
			if (warning != null)
			{
				Log.LogWarning((object)warning);
			}
			new Harmony("com.dfg.bifrostgateway").PatchAll(typeof(BifrostGatewayPlugin).Assembly);
			Log.LogInfo((object)("Bifrost Gateway 1.0.1 ready with " + _servers.Count + " server(s). Automatic passwords: " + (GatewayJoin.CanSupplyPassword ? "available" : "UNAVAILABLE, the game will prompt") + ". Character-select flow: " + (GatewayJoin.CanSelectCharacter ? "available" : "unavailable, rows will join directly") + "."));
			if (!GatewayJoin.CanSupplyPassword)
			{
				Log.LogWarning((object)"FejdStartup.set_ServerPassword was not found on this build. Servers with a saved password will still connect, but the game will ask for it by hand.");
			}
		}

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

		private void OnGUI()
		{
			if (!_loaded || Settings == null || !Settings.Enabled.Value)
			{
				return;
			}
			FejdStartup instance = FejdStartup.instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)ZNet.instance != (Object)null))
			{
				bool num = (Object)(object)instance.m_mainMenu != (Object)null && instance.m_mainMenu.activeSelf;
				bool flag = (Object)(object)instance.m_characterSelectScreen != (Object)null && instance.m_characterSelectScreen.activeSelf;
				if (num || flag)
				{
					GatewayPanel.Draw(this, _servers);
				}
			}
		}
	}
	internal sealed class GatewaySettings
	{
		internal ConfigEntry<bool> Enabled;

		internal ConfigEntry<float> RefreshSeconds;

		internal ConfigEntry<float> PanelWidth;

		internal ConfigEntry<float> PanelLeft;

		internal ConfigEntry<float> PanelTop;

		internal GatewaySettings(ConfigFile config)
		{
			Enabled = config.Bind<bool>("General", "Enabled", true, "Show the Bifrost Gateway panel on the main menu.");
			RefreshSeconds = config.Bind<float>("General", "RefreshSeconds", 30f, "How often, in seconds, to re-read player counts for every listed server. Minimum 5.");
			PanelWidth = config.Bind<float>("Layout", "PanelWidth", 460f, "Width of the panel in pixels.");
			PanelLeft = config.Bind<float>("Layout", "PanelLeft", 40f, "Distance of the panel from the left edge, in pixels.");
			PanelTop = config.Bind<float>("Layout", "PanelTop", 60f, "Distance of the panel from the top of the screen, in pixels.");
		}
	}
	internal static class JoinFactory
	{
		internal static ServerJoinData Dedicated(string address, int port)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			return new ServerJoinData(new ServerJoinDataDedicated((address ?? "").Trim(), (ushort)port));
		}
	}
	internal static class GatewayJoin
	{
		private static readonly MethodInfo SetServerPassword = AccessTools.Method(typeof(FejdStartup), "set_ServerPassword", (Type[])null, (Type[])null);

		private static readonly MethodInfo ProceedJoinRequest = AccessTools.Method(typeof(FejdStartup), "ProceedJoinRequest", (Type[])null, (Type[])null);

		private static bool s_passwordSetterWarned;

		private static bool s_proceedJoinWarned;

		private static string s_pendingEndpoint;

		internal static bool CanSupplyPassword => SetServerPassword != null;

		internal static bool CanSelectCharacter => ProceedJoinRequest != null;

		internal static string PendingEndpoint => s_pendingEndpoint;

		internal static bool Connect(GatewayServer server, Action<string, bool> feedback)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if (server == null)
			{
				feedback?.Invoke("No server selected.", arg2: true);
				return false;
			}
			if (!server.IsUsable(out var problem))
			{
				feedback?.Invoke(problem, arg2: true);
				return false;
			}
			FejdStartup instance = FejdStartup.instance;
			if ((Object)(object)instance == (Object)null)
			{
				feedback?.Invoke("Not at the main menu.", arg2: true);
				return false;
			}
			if (!SupplyPassword(server.Password))
			{
				feedback?.Invoke("Cannot set the join password on this build; the game will ask for it.", arg2: true);
			}
			try
			{
				ServerJoinData val = JoinFactory.Dedicated(server.Address, server.SafePort);
				bool flag = TryProceedWithCharacterSelect(instance, val);
				if (!flag)
				{
					instance.SetServerToJoin(val);
					instance.JoinServer();
				}
				s_pendingEndpoint = server.Endpoint;
				if (feedback != null)
				{
					string text = (string.IsNullOrEmpty(server.Password) ? "" : " with its saved password");
					if (flag)
					{
						feedback("Select your character to join " + server.DisplayName + text + "...", arg2: false);
					}
					else
					{
						feedback("Connecting to " + server.DisplayName + text + "...", arg2: false);
					}
				}
				return true;
			}
			catch (Exception ex)
			{
				s_pendingEndpoint = null;
				feedback?.Invoke("Could not start the connection: " + ex.Message, arg2: true);
				BifrostGatewayPlugin.Log.LogError((object)("Join failed for " + server.Endpoint + ": " + ex));
				return false;
			}
		}

		private static bool TryProceedWithCharacterSelect(FejdStartup startup, ServerJoinData join)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (ProceedJoinRequest == null)
			{
				if (!s_proceedJoinWarned)
				{
					s_proceedJoinWarned = true;
					BifrostGatewayPlugin.Log.LogWarning((object)"FejdStartup.ProceedJoinRequest not found on this build. Rows will join immediately without the character-selection prompt. Re-run verify_api.ps1 after a game update.");
				}
				return false;
			}
			try
			{
				ProceedJoinRequest.Invoke(startup, new object[1] { join });
				return true;
			}
			catch (Exception ex)
			{
				if (!s_proceedJoinWarned)
				{
					s_proceedJoinWarned = true;
					BifrostGatewayPlugin.Log.LogError((object)("Could not invoke FejdStartup.ProceedJoinRequest: " + ex.Message));
				}
				return false;
			}
		}

		private static bool SupplyPassword(string password)
		{
			if (SetServerPassword == null)
			{
				if (!s_passwordSetterWarned)
				{
					s_passwordSetterWarned = true;
					BifrostGatewayPlugin.Log.LogWarning((object)"FejdStartup.set_ServerPassword not found. Saved passwords will not be applied automatically and the game will prompt. Re-run verify_api.ps1 after a game update.");
				}
				return false;
			}
			try
			{
				SetServerPassword.Invoke(null, new object[1] { password ?? "" });
				return true;
			}
			catch (Exception ex)
			{
				if (!s_passwordSetterWarned)
				{
					s_passwordSetterWarned = true;
					BifrostGatewayPlugin.Log.LogError((object)("Could not set the join password: " + ex.Message));
				}
				return false;
			}
		}
	}
	[HarmonyPatch]
	internal static class PasswordCleanupPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(ZNet), "RPC_ClientHandshake", (Type[])null, (Type[])null);
		}

		private static void Postfix()
		{
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(FejdStartup), "set_ServerPassword", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					methodInfo.Invoke(null, new object[1] { "" });
				}
			}
			catch (Exception ex)
			{
				BifrostGatewayPlugin.Log.LogWarning((object)("Could not clear the saved join password: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	internal static class CharacterSelectBackPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(FejdStartup), "OnSelelectCharacterBack", (Type[])null, (Type[])null);
		}

		private static void Postfix()
		{
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(FejdStartup), "set_ServerPassword", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					methodInfo.Invoke(null, new object[1] { "" });
				}
			}
			catch (Exception ex)
			{
				BifrostGatewayPlugin.Log.LogWarning((object)("Could not clear the saved join password on character-select back: " + ex.Message));
			}
		}
	}
	internal static class GatewayPanel
	{
		private const float DefaultPanelWidth = 460f;

		private const float DefaultPanelLeft = 40f;

		private const float DefaultPanelTop = 60f;

		private const float HeaderHeight = 64f;

		private const float RowHeight = 46f;

		private const float FooterHeight = 44f;

		private const float MessageHeight = 20f;

		private const float Pad = 12f;

		private const float RowEditWidth = 26f;

		private static readonly List<ServerStatus> Statuses = new List<ServerStatus>();

		private static Vector2 Scroll;

		private static DateTime s_nextProbeUtc = DateTime.MinValue;

		private static int s_probedCount = -1;

		private static bool s_editing;

		private static int s_editIndex = -1;

		private static GatewayServer s_draft;

		private static string s_portText = "2480";

		private static bool s_portDirty;

		private static string s_message;

		private static bool s_messageIsError;

		private static bool s_loggedGate;

		internal static void Draw(BifrostGatewayPlugin plugin, List<GatewayServer> servers)
		{
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			Cursor.visible = true;
			Cursor.lockState = (CursorLockMode)0;
			if (servers == null)
			{
				servers = new List<GatewayServer>();
			}
			RefreshIfDue(servers, plugin);
			float num = Mathf.Clamp(plugin.Settings.PanelWidth.Value, 300f, 900f);
			float num2 = Mathf.Max(0f, plugin.Settings.PanelLeft.Value);
			float num3 = Mathf.Max(0f, plugin.Settings.PanelTop.Value);
			float num4 = (string.IsNullOrEmpty(s_message) ? 0f : 20f);
			float num5 = 120f + (float)servers.Count * 46f + (s_editing ? 190f : 0f) + 96f + num4;
			float num6 = Mathf.Min(Mathf.Max((float)Screen.height - num3 * 2f, 240f), num5);
			num6 = Mathf.Max(num6, Mathf.Min(320f, Mathf.Max((float)Screen.height - num3 * 2f, 240f)));
			Rect rect = default(Rect);
			((Rect)(ref rect))..ctor(num2, num3, num, num6);
			GatewayTheme.DrawFrame(rect);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref rect)).x + 12f, ((Rect)(ref rect)).y + 12f, ((Rect)(ref rect)).width - 24f, ((Rect)(ref rect)).height - 24f);
			float y = ((Rect)(ref val)).y;
			y = DrawHeader(new Rect(((Rect)(ref val)).x, y, ((Rect)(ref val)).width, 64f));
			Rect rect2 = default(Rect);
			((Rect)(ref rect2))..ctor(((Rect)(ref val)).x, ((Rect)(ref rect)).yMax - 12f - 44f, ((Rect)(ref val)).width, 44f);
			float num7 = ((Rect)(ref rect2)).y - 4f - y - num4;
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(((Rect)(ref val)).x, y, ((Rect)(ref val)).width, Mathf.Max(num7, 24f));
			float num8 = (float)servers.Count * 46f;
			if (s_editing)
			{
				num8 += 182f;
			}
			bool flag = num8 > ((Rect)(ref val2)).height;
			if (flag)
			{
				Scroll = GUI.BeginScrollView(val2, Scroll, new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y, ((Rect)(ref val2)).width, num8), GUIStyle.none, GUIStyle.none);
			}
			float num9 = ((Rect)(ref val2)).y;
			for (int i = 0; i < servers.Count; i++)
			{
				ServerStatus status = ((i < Statuses.Count) ? Statuses[i] : default(ServerStatus));
				DrawRow(new Rect(((Rect)(ref val2)).x, num9, ((Rect)(ref val2)).width, 42f), i, servers[i], status);
				num9 += 46f;
			}
			if (servers.Count == 0)
			{
				GatewayTheme.Label(new Rect(((Rect)(ref val2)).x + 12f, num9 + 12f, ((Rect)(ref val2)).width - 24f, 40f), "No servers yet. Add one below.", 15, bold: false, (TextAnchor)0, GatewayTheme.MutedText);
			}
			if (s_editing)
			{
				DrawEditor(new Rect(((Rect)(ref val2)).x, num9 + 6f, ((Rect)(ref val2)).width, 178f), plugin, servers);
			}
			if (flag)
			{
				GUI.EndScrollView();
			}
			DrawFooter(rect2, plugin, servers);
			if (num4 > 0f)
			{
				DrawMessage(new Rect(((Rect)(ref val)).x, ((Rect)(ref rect2)).y - num4, ((Rect)(ref val)).width, num4));
			}
		}

		private static float DrawHeader(Rect rect)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			GatewayTheme.DrawRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 30f), GatewayTheme.HeaderBg);
			GatewayTheme.RichLabel(new Rect(((Rect)(ref rect)).x + 12f, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width - 24f, 30f), "<b><color=#FFD760>BIFROST GATEWAY</color></b>", 19, bold: true, (TextAnchor)3);
			GatewayTheme.Label(new Rect(((Rect)(ref rect)).x + 12f, ((Rect)(ref rect)).y + 28f, ((Rect)(ref rect)).width - 24f, 24f), "Click a realm, then pick your character. Passwords supplied for you.", 13, bold: false, (TextAnchor)3, GatewayTheme.MutedText);
			return ((Rect)(ref rect)).yMax;
		}

		private static void DrawRow(Rect rect, int index, GatewayServer server, ServerStatus status)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			bool flag = ((Rect)(ref rect)).Contains(Event.current.mousePosition) && !s_editing;
			GatewayTheme.DrawRect(rect, flag ? GatewayTheme.CardBgHover : GatewayTheme.CardBg);
			GatewayTheme.DrawBorder(rect, flag ? GatewayTheme.CardBorderHover : GatewayTheme.CardBorder, 1f);
			if (s_editing && s_editIndex == index)
			{
				GatewayTheme.DrawRect(new Rect(((Rect)(ref rect)).x + 1f, ((Rect)(ref rect)).y + 1f, 3f, ((Rect)(ref rect)).height - 2f), GatewayTheme.WindowBorder);
			}
			float num = ((Rect)(ref rect)).x + 12f + 4f;
			float num2 = 92f;
			float num3 = (s_editing ? 0f : 26f);
			float num4 = ((Rect)(ref rect)).width - num2 - num3 - 24f - 4f;
			GatewayTheme.RichLabel(richText: "<color=#EAF2FA>" + Escape(server.DisplayName) + "</color>", rect: new Rect(num, ((Rect)(ref rect)).y + 4f, num4, 20f), fontSize: 16, bold: true, anchor: (TextAnchor)3);
			GatewayTheme.Label(new Rect(num, ((Rect)(ref rect)).y + 22f, num4, 18f), server.Endpoint, 12, bold: false, (TextAnchor)3, GatewayTheme.MutedText);
			DrawCounts(new Rect(((Rect)(ref rect)).xMax - num2 - num3, ((Rect)(ref rect)).y, num2 - 12f, ((Rect)(ref rect)).height), server, status);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width - num3, ((Rect)(ref rect)).height);
			if (!s_editing && GUI.Button(val, GUIContent.none, GUIStyle.none))
			{
				s_message = null;
				GatewayJoin.Connect(server, Say);
			}
			if (!s_editing)
			{
				Rect val2 = default(Rect);
				((Rect)(ref val2))..ctor(((Rect)(ref rect)).xMax - 26f - 2f, ((Rect)(ref rect)).y + 8f, 26f, ((Rect)(ref rect)).height - 16f);
				bool flag2 = ((Rect)(ref val2)).Contains(Event.current.mousePosition);
				GatewayTheme.Label(val2, "✎", 16, bold: false, (TextAnchor)4, flag2 ? GatewayTheme.GoldText : GatewayTheme.MutedText);
				if (GUI.Button(val2, GUIContent.none, GUIStyle.none))
				{
					s_draft = server.Copy();
					s_portText = s_draft.Port.ToString();
					s_portDirty = false;
					s_editIndex = index;
					s_editing = true;
					s_message = null;
				}
			}
		}

		private static void DrawCounts(Rect rect, GatewayServer server, ServerStatus status)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			string text;
			Color color;
			if (!status.Probed)
			{
				text = ((status.Detail == null) ? "unknown" : status.Detail);
				color = GatewayTheme.MutedText;
			}
			else if (!status.Online)
			{
				text = "offline";
				color = GatewayTheme.RedText;
			}
			else if (status.Limit != 0 && status.Players >= status.Limit)
			{
				text = status.Players + "/" + status.Limit + "  full";
				color = GatewayTheme.RedText;
			}
			else if (status.Limit != 0 && status.Players != 0)
			{
				text = status.Players + "/" + status.Limit;
				color = GatewayTheme.GreenText;
			}
			else
			{
				text = ((status.Limit != 0) ? ("0/" + status.Limit) : "online");
				color = GatewayTheme.CyanText;
			}
			if (!string.IsNullOrEmpty(server.Password))
			{
				text = "● " + text;
				color = GatewayTheme.GoldText;
			}
			GatewayTheme.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 6f, ((Rect)(ref rect)).width, 18f), text, 14, bold: false, (TextAnchor)5, color);
			if (status.VersionMismatch && !string.IsNullOrEmpty(status.Version))
			{
				GatewayTheme.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 23f, ((Rect)(ref rect)).width, 16f), "⚠ v" + status.Version, 11, bold: true, (TextAnchor)5, GatewayTheme.RedText);
			}
			else if (!GatewayJoin.CanSupplyPassword && !string.IsNullOrEmpty(server.Password))
			{
				GatewayTheme.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 23f, ((Rect)(ref rect)).width, 16f), "password unsupported", 11, bold: false, (TextAnchor)5, GatewayTheme.RedText);
			}
		}

		private static void DrawEditor(Rect rect, BifrostGatewayPlugin plugin, List<GatewayServer> servers)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			GatewayTheme.DrawRect(rect, GatewayTheme.HeaderBg);
			GatewayTheme.DrawBorder(rect, GatewayTheme.WindowBorder, 1f);
			float num = ((Rect)(ref rect)).y + 8f;
			float num2 = 74f;
			float num3 = ((Rect)(ref rect)).x + num2 + 8f;
			float num4 = ((Rect)(ref rect)).width - num2 - 16f;
			GatewayTheme.Label(new Rect(((Rect)(ref rect)).x + 8f, num, num2, 20f), "Name", 13, bold: false, (TextAnchor)3, GatewayTheme.MutedText);
			s_draft.Name = GatewayTheme.TextField(new Rect(num3, num, num4, 22f), s_draft.Name, 14);
			num += 26f;
			GatewayTheme.Label(new Rect(((Rect)(ref rect)).x + 8f, num, num2, 20f), "Address", 13, bold: false, (TextAnchor)3, GatewayTheme.MutedText);
			s_draft.Address = GatewayTheme.TextField(new Rect(num3, num, num4, 22f), s_draft.Address, 14);
			num += 26f;
			GatewayTheme.Label(new Rect(((Rect)(ref rect)).x + 8f, num, num2, 20f), "Port", 13, bold: false, (TextAnchor)3, GatewayTheme.MutedText);
			string text = GatewayTheme.TextField(new Rect(num3, num, 80f, 22f), s_portText, 14);
			if (text != s_portText)
			{
				s_portText = text;
				s_portDirty = true;
			}
			if (!s_portDirty && int.TryParse(s_portText, out var result))
			{
				s_draft.Port = result;
			}
			num += 26f;
			GatewayTheme.Label(new Rect(((Rect)(ref rect)).x + 8f, num, num2, 20f), "Password", 13, bold: false, (TextAnchor)3, GatewayTheme.MutedText);
			s_draft.Password = GatewayTheme.TextField(new Rect(num3, num, num4, 22f), s_draft.Password, 14);
			float num5 = ((Rect)(ref rect)).yMax - 32f;
			float num6 = (((Rect)(ref rect)).width - 20f) / 3f;
			if (GatewayTheme.Button(new Rect(((Rect)(ref rect)).x + 8f, num5, num6, 24f), "Save", enabled: true, GatewayTheme.GoldText, 14))
			{
				Save(plugin, servers);
			}
			if (GatewayTheme.Button(new Rect(((Rect)(ref rect)).x + 8f + num6 + 4f, num5, num6, 24f), "Cancel", enabled: true, GatewayTheme.MutedText, 14))
			{
				CloseEditor();
			}
			if (s_editIndex >= 0 && s_editIndex < servers.Count && GatewayTheme.Button(new Rect(((Rect)(ref rect)).x + 8f + (num6 + 4f) * 2f, num5, num6, 24f), "Delete", enabled: true, GatewayTheme.RedText, 14))
			{
				Remove(plugin, servers, s_editIndex);
			}
		}

		private static void DrawFooter(Rect rect, BifrostGatewayPlugin plugin, List<GatewayServer> servers)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_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_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			float num = 8f;
			float num2 = (((Rect)(ref rect)).width - num * 3f) / 4f;
			float y = ((Rect)(ref rect)).y;
			if (GatewayTheme.Button(new Rect(((Rect)(ref rect)).x, y, num2, 28f), "Add server", enabled: true, GatewayTheme.GoldText, 14))
			{
				s_draft = new GatewayServer();
				s_portText = s_draft.Port.ToString();
				s_portDirty = false;
				s_editIndex = -1;
				s_editing = true;
				s_message = null;
			}
			if (GatewayTheme.Button(new Rect(((Rect)(ref rect)).x + (num2 + num), y, num2, 28f), "Refresh", enabled: true, GatewayTheme.CyanText, 14))
			{
				ForceRefresh(servers);
			}
			if (GatewayTheme.Button(new Rect(((Rect)(ref rect)).x + (num2 + num) * 2f, y, num2, 28f), "Edit first", enabled: true, GatewayTheme.WhiteText, 14))
			{
				if (servers.Count > 0)
				{
					s_draft = servers[0].Copy();
					s_portText = s_draft.Port.ToString();
					s_portDirty = false;
					s_editIndex = 0;
					s_editing = true;
					s_message = null;
				}
				else
				{
					Say("Nothing to edit yet.", isError: true);
				}
			}
			if (GatewayTheme.Button(new Rect(((Rect)(ref rect)).x + (num2 + num) * 3f, y, num2, 28f), "Close editor", enabled: true, GatewayTheme.MutedText, 14))
			{
				CloseEditor();
			}
		}

		private static void DrawMessage(Rect rect)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrEmpty(s_message))
			{
				GatewayTheme.Label(rect, s_message, 13, bold: false, (TextAnchor)3, s_messageIsError ? GatewayTheme.RedText : GatewayTheme.GreenText);
			}
		}

		private static void Save(BifrostGatewayPlugin plugin, List<GatewayServer> servers)
		{
			if (int.TryParse(s_portText, out var result))
			{
				s_draft.Port = result;
			}
			if (!s_draft.IsUsable(out var problem))
			{
				Say(problem, isError: true);
				return;
			}
			if (s_editIndex >= 0 && s_editIndex < servers.Count)
			{
				servers[s_editIndex] = s_draft.Copy();
				Say("Saved " + s_draft.DisplayName + ".", isError: false);
			}
			else
			{
				servers.Add(s_draft.Copy());
				Say("Added " + s_draft.DisplayName + ".", isError: false);
			}
			if (!GatewayStore.Save(servers, out problem))
			{
				Say("Added, but could not write bifrost_config.json: " + problem, isError: true);
				return;
			}
			CloseEditor();
			ForceRefresh(servers);
		}

		private static void Remove(BifrostGatewayPlugin plugin, List<GatewayServer> servers, int index)
		{
			if (index >= 0 && index < servers.Count)
			{
				string displayName = servers[index].DisplayName;
				servers.RemoveAt(index);
				if (!GatewayStore.Save(servers, out var error))
				{
					Say("Removed, but could not write bifrost_config.json: " + error, isError: true);
				}
				else
				{
					Say("Removed " + displayName + ".", isError: false);
				}
				CloseEditor();
				ForceRefresh(servers);
			}
		}

		private static void CloseEditor()
		{
			s_editing = false;
			s_editIndex = -1;
			s_draft = null;
			s_portText = "2480";
			s_portDirty = false;
		}

		internal static void Say(string message, bool isError)
		{
			s_message = message;
			s_messageIsError = isError;
			if (isError)
			{
				BifrostGatewayPlugin.Log.LogWarning((object)("Bifrost Gateway: " + message));
			}
			else
			{
				BifrostGatewayPlugin.Log.LogInfo((object)("Bifrost Gateway: " + message));
			}
		}

		private static void RefreshIfDue(List<GatewayServer> servers, BifrostGatewayPlugin plugin)
		{
			if (servers.Count != s_probedCount)
			{
				s_probedCount = servers.Count;
				s_nextProbeUtc = DateTime.MinValue;
			}
			if (!(DateTime.UtcNow < s_nextProbeUtc))
			{
				s_nextProbeUtc = DateTime.UtcNow.AddSeconds(Mathf.Max(5f, plugin.Settings.RefreshSeconds.Value));
				Statuses.Clear();
				for (int i = 0; i < servers.Count; i++)
				{
					Statuses.Add(ServerProbe.Probe(servers[i]));
				}
				if (!s_loggedGate)
				{
					s_loggedGate = true;
					BifrostGatewayPlugin.Log.LogInfo((object)("Gateway panel shown on the main menu with " + servers.Count + " server(s). Automatic passwords: " + (GatewayJoin.CanSupplyPassword ? "available" : "UNAVAILABLE") + "."));
				}
			}
		}

		private static void ForceRefresh(List<GatewayServer> servers)
		{
			s_nextProbeUtc = DateTime.MinValue;
			s_probedCount = -1;
			BifrostGatewayPlugin instance = BifrostGatewayPlugin.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				RefreshIfDue(servers, instance);
			}
		}

		private static string Escape(string value)
		{
			return (value ?? "").Replace("<", "&lt;").Replace(">", "&gt;");
		}
	}
	internal sealed class GatewayServer
	{
		public string Name = "";

		public string Address = "";

		public int Port = 2480;

		public string Password = "";

		internal int SafePort
		{
			get
			{
				if (Port >= 1 && Port <= 65535)
				{
					return Port;
				}
				return 2480;
			}
		}

		internal string Endpoint => (Address ?? "").Trim() + ":" + SafePort;

		internal string DisplayName
		{
			get
			{
				if (!string.IsNullOrWhiteSpace(Name))
				{
					return Name;
				}
				return Endpoint;
			}
		}

		internal bool IsUsable(out string problem)
		{
			if (string.IsNullOrWhiteSpace(Address))
			{
				problem = "Address is required.";
				return false;
			}
			if (Port < 1 || Port > 65535)
			{
				problem = "Port must be between 1 and 65535.";
				return false;
			}
			problem = null;
			return true;
		}

		internal GatewayServer Copy()
		{
			return new GatewayServer
			{
				Name = (Name ?? ""),
				Address = (Address ?? ""),
				Port = Port,
				Password = (Password ?? "")
			};
		}
	}
	internal sealed class GatewayFile
	{
		public List<GatewayServer> Servers = new List<GatewayServer>();
	}
	internal static class GatewayStore
	{
		internal const string FileName = "bifrost_config.json";

		internal static string FilePath => Path.Combine(Paths.PluginPath, "BifrostGateway", "bifrost_config.json");

		internal static List<GatewayServer> Load(out string warning)
		{
			warning = null;
			try
			{
				string filePath = FilePath;
				if (!File.Exists(filePath))
				{
					return new List<GatewayServer>();
				}
				GatewayFile gatewayFile = JsonConvert.DeserializeObject<GatewayFile>(File.ReadAllText(filePath));
				List<GatewayServer> list = new List<GatewayServer>();
				if (gatewayFile?.Servers != null)
				{
					foreach (GatewayServer server in gatewayFile.Servers)
					{
						if (server != null && server.IsUsable(out var _))
						{
							list.Add(server);
						}
					}
				}
				return list;
			}
			catch (Exception ex) when (ex is IOException || ex is JsonException || ex is UnauthorizedAccessException)
			{
				warning = "Could not read bifrost_config.json: " + ex.Message;
				return new List<GatewayServer>();
			}
		}

		internal static bool Save(List<GatewayServer> servers, out string error)
		{
			error = null;
			try
			{
				string filePath = FilePath;
				string directoryName = Path.GetDirectoryName(filePath);
				if (!string.IsNullOrEmpty(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				GatewayFile gatewayFile = new GatewayFile
				{
					Servers = (servers ?? new List<GatewayServer>())
				};
				string text = filePath + ".tmp";
				File.WriteAllText(text, JsonConvert.SerializeObject((object)gatewayFile, (Formatting)1));
				if (File.Exists(filePath))
				{
					File.Delete(filePath);
				}
				File.Move(text, filePath);
				return true;
			}
			catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException)
			{
				error = ex.Message;
				return false;
			}
		}
	}
	internal static class GatewayTheme
	{
		internal static readonly Color Backdrop = new Color(0f, 0f, 0f, 0.76f);

		internal static readonly Color WindowBg = new Color(0.08f, 0.1f, 0.14f, 0.98f);

		internal static readonly Color WindowBorder = new Color(0.74f, 0.58f, 0.28f, 1f);

		internal static readonly Color WindowBorderInner = new Color(0.18f, 0.23f, 0.32f, 0.85f);

		internal static readonly Color CardBg = new Color(0.09f, 0.11f, 0.16f, 0.96f);

		internal static readonly Color CardBgHover = new Color(0.14f, 0.17f, 0.24f, 0.98f);

		internal static readonly Color CardBorder = new Color(0.22f, 0.28f, 0.38f, 0.85f);

		internal static readonly Color CardBorderHover = new Color(0.74f, 0.58f, 0.28f, 1f);

		internal static readonly Color HeaderBg = new Color(0.12f, 0.16f, 0.22f, 1f);

		internal static readonly Color FieldBg = new Color(0.05f, 0.06f, 0.09f, 0.95f);

		internal static readonly Color GoldText = new Color(1f, 0.84f, 0.38f, 1f);

		internal static readonly Color WhiteText = new Color(0.92f, 0.95f, 0.98f, 1f);

		internal static readonly Color MutedText = new Color(0.6f, 0.66f, 0.75f, 1f);

		internal static readonly Color CyanText = new Color(0.4f, 0.8f, 1f, 1f);

		internal static readonly Color GreenText = new Color(0.38f, 0.88f, 0.48f, 1f);

		internal static readonly Color AmberText = new Color(0.95f, 0.7f, 0.28f, 1f);

		internal static readonly Color RedText = new Color(0.95f, 0.38f, 0.38f, 1f);

		private static readonly Dictionary<string, GUIStyle> TextStyles = new Dictionary<string, GUIStyle>();

		private static readonly Dictionary<string, GUIStyle> FieldStyles = new Dictionary<string, GUIStyle>();

		private static Texture2D s_white;

		internal static Texture2D White
		{
			get
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Expected O, but got Unknown
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)s_white == (Object)null)
				{
					s_white = new Texture2D(1, 1, (TextureFormat)4, false)
					{
						name = "BifrostGateway.White",
						hideFlags = (HideFlags)61,
						filterMode = (FilterMode)0,
						wrapMode = (TextureWrapMode)1
					};
					s_white.SetPixel(0, 0, Color.white);
					s_white.Apply();
				}
				return s_white;
			}
		}

		internal static void DrawRect(Rect rect, Color color)
		{
			//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_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!(((Rect)(ref rect)).width <= 0f) && !(((Rect)(ref rect)).height <= 0f))
			{
				Color color2 = GUI.color;
				GUI.color = color;
				GUI.DrawTexture(rect, (Texture)(object)White);
				GUI.color = color2;
			}
		}

		internal static void DrawBorder(Rect rect, Color color, float thickness)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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 (!(((Rect)(ref rect)).width <= 0f) && !(((Rect)(ref rect)).height <= 0f) && !(thickness <= 0f))
			{
				DrawRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), color);
				DrawRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), color);
				DrawRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color);
				DrawRect(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color);
			}
		}

		internal static void DrawFrame(Rect rect)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			DrawRect(rect, WindowBg);
			DrawBorder(rect, WindowBorder, 2f);
			DrawBorder(new Rect(((Rect)(ref rect)).x + 4f, ((Rect)(ref rect)).y + 4f, ((Rect)(ref rect)).width - 8f, ((Rect)(ref rect)).height - 8f), WindowBorderInner, 1f);
		}

		internal static bool Button(Rect rect, string label, bool enabled, Color textColor, int fontSize = 15)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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)
			if (!enabled)
			{
				DrawRect(rect, new Color(CardBg.r, CardBg.g, CardBg.b, 0.5f));
				DrawBorder(rect, new Color(CardBorder.r, CardBorder.g, CardBorder.b, 0.4f), 1f);
				Label(rect, label, fontSize, bold: true, (TextAnchor)4, new Color(textColor.r, textColor.g, textColor.b, 0.4f));
				return false;
			}
			bool flag = ((Rect)(ref rect)).Contains(Event.current.mousePosition);
			DrawRect(rect, flag ? CardBgHover : CardBg);
			DrawBorder(rect, flag ? CardBorderHover : CardBorder, 1f);
			bool num = GUI.Button(rect, GUIContent.none, GUIStyle.none);
			if (num)
			{
				Event.current.Use();
			}
			GUI.Label(rect, label, Text(fontSize, bold: true, (TextAnchor)4, textColor));
			return num;
		}

		internal static void Label(Rect rect, string text, int fontSize, bool bold, TextAnchor anchor, Color color)
		{
			//IL_0000: 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_000f: Unknown result type (might be due to invalid IL or missing references)
			GUI.Label(rect, text ?? "", Text(fontSize, bold, anchor, color));
		}

		internal static void RichLabel(Rect rect, string richText, int fontSize, bool bold, TextAnchor anchor)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			GUI.Label(rect, richText, Text(fontSize, bold, anchor, Color.white));
		}

		internal static string TextField(Rect rect, string value, int fontSize)
		{
			//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_0006: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			Color color = GUI.color;
			GUI.color = Color.white;
			string result = GUI.TextField(rect, value ?? "", Field(fontSize));
			GUI.color = color;
			return result;
		}

		private unsafe static GUIStyle Text(int fontSize, bool bold, TextAnchor anchor, Color color)
		{
			//IL_004c: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			string key = fontSize + "|" + (bold ? "b" : "n") + "|" + ((object)(*(TextAnchor*)(&anchor))/*cast due to .constrained prefix*/).ToString() + "|" + Hex(color);
			if (TextStyles.TryGetValue(key, out var value))
			{
				return value;
			}
			value = new GUIStyle(GUI.skin.label)
			{
				fontSize = fontSize,
				fontStyle = (FontStyle)(bold ? 1 : 0),
				alignment = anchor,
				richText = true,
				wordWrap = false,
				clipping = (TextClipping)1
			};
			value.normal.textColor = color;
			value.hover.textColor = color;
			value.active.textColor = color;
			value.onNormal.textColor = color;
			value.onHover.textColor = color;
			value.onActive.textColor = color;
			TextStyles[key] = value;
			return value;
		}

		private static GUIStyle Field(int fontSize)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_003e: Expected O, but got Unknown
			string key = fontSize.ToString();
			if (FieldStyles.TryGetValue(key, out var value))
			{
				return value;
			}
			value = new GUIStyle(GUI.skin.textField)
			{
				fontSize = fontSize,
				alignment = (TextAnchor)3,
				richText = false
			};
			FieldStyles[key] = value;
			return value;
		}

		internal static string Hex(Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Clamp(Mathf.RoundToInt(color.r * 255f), 0, 255);
			int num2 = Mathf.Clamp(Mathf.RoundToInt(color.g * 255f), 0, 255);
			int num3 = Mathf.Clamp(Mathf.RoundToInt(color.b * 255f), 0, 255);
			return num.ToString("X2") + num2.ToString("X2") + num3.ToString("X2");
		}
	}
	internal struct ServerStatus
	{
		internal bool Probed;

		internal bool Online;

		internal uint Players;

		internal uint Limit;

		internal bool PasswordProtected;

		internal string ServerName;

		internal string Version;

		internal bool VersionMismatch;

		internal string Detail;
	}
	internal static class ServerProbe
	{
		internal unsafe static ServerStatus Probe(GatewayServer server)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: 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_0131: 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_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			ServerStatus result = default(ServerStatus);
			if (server == null)
			{
				result.Detail = "no server";
				return result;
			}
			if (!server.IsUsable(out var problem))
			{
				result.Detail = problem;
				return result;
			}
			if ((Object)(object)MultiBackendMatchmaking.Instance == (Object)null)
			{
				result.Detail = "matchmaking not ready";
				return result;
			}
			try
			{
				ServerJoinData val = JoinFactory.Dedicated(server.Address, server.SafePort);
				if (!((ServerJoinData)(ref val)).IsValid)
				{
					result.Detail = "address not accepted";
					return result;
				}
				ServerMatchmakingData serverMatchmakingData = MultiBackendMatchmaking.GetServerMatchmakingData(val, DateTime.MinValue);
				result.Probed = true;
				result.Online = ((ServerMatchmakingData)(ref serverMatchmakingData)).IsValid && OnlineStatusExtentions.IsOnline(serverMatchmakingData.m_onlineStatus);
				result.Players = serverMatchmakingData.m_playerCount;
				result.Limit = serverMatchmakingData.m_playerLimit;
				result.PasswordProtected = serverMatchmakingData.m_isPasswordProtected;
				result.ServerName = serverMatchmakingData.m_serverName;
				GameVersion gameVersion = serverMatchmakingData.m_gameVersion;
				result.Version = (((object)gameVersion == null) ? null : ((object)(*(GameVersion*)(&gameVersion))/*cast due to .constrained prefix*/).ToString());
				GameVersion currentVersion = Version.CurrentVersion;
				result.VersionMismatch = (object)gameVersion != null && (object)currentVersion != null && ((GameVersion)(ref gameVersion)).IsValid() && (gameVersion.m_major != currentVersion.m_major || gameVersion.m_minor != currentVersion.m_minor || gameVersion.m_patch != currentVersion.m_patch);
				if (((ServerMatchmakingData)(ref serverMatchmakingData)).IsValid && !result.Online)
				{
					result.Detail = "offline";
				}
				return result;
			}
			catch (Exception ex)
			{
				result.Probed = false;
				result.Detail = ex.Message;
				return result;
			}
		}
	}
}