Decompiled source of PhotonNetworkChecker v1.0.0

TFS_PhotonNetworkChecker.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
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: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 TFS_PhotonNetworkChecker
{
	internal class PhotonStatusHUD : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass8_0
		{
			public string host;

			internal bool <CheckAll>b__0()
			{
				return CheckIP(host);
			}

			internal bool <CheckAll>b__1()
			{
				return CheckHTTP(host);
			}

			internal bool <CheckAll>b__2()
			{
				return CheckWSS(host);
			}
		}

		[CompilerGenerated]
		private sealed class <CheckAll>d__8 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public PhotonStatusHUD <>4__this;

			private int <i>5__2;

			private bool[] <results>5__3;

			private bool[] <done>5__4;

			private float <waited>5__5;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <CheckAll>d__8(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<results>5__3 = null;
				<done>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				int num = <>1__state;
				PhotonStatusHUD photonStatusHUD = <>4__this;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					goto IL_0139;
				}
				<>1__state = -1;
				photonStatusHUD.checking = true;
				for (int i = 0; i < Servers.Length; i++)
				{
					for (int j = 0; j < 3; j++)
					{
						photonStatusHUD.statuses[i, j] = null;
					}
				}
				photonStatusHUD.UpdateText();
				<i>5__2 = 0;
				goto IL_01c9;
				IL_0139:
				if ((!<done>5__4[0] || !<done>5__4[1] || !<done>5__4[2]) && <waited>5__5 < 8f)
				{
					<waited>5__5 += Time.unscaledDeltaTime;
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				for (int k = 0; k < 3; k++)
				{
					photonStatusHUD.statuses[<i>5__2, k] = <done>5__4[k] && <results>5__3[k];
				}
				photonStatusHUD.UpdateText();
				<results>5__3 = null;
				<done>5__4 = null;
				<i>5__2++;
				goto IL_01c9;
				IL_01c9:
				if (<i>5__2 < Servers.Length)
				{
					<>c__DisplayClass8_0 CS$<>8__locals0 = new <>c__DisplayClass8_0
					{
						host = Servers[<i>5__2].host
					};
					<results>5__3 = new bool[3];
					<done>5__4 = new bool[3];
					SpawnCheck(0, () => CheckIP(CS$<>8__locals0.host), <results>5__3, <done>5__4);
					SpawnCheck(1, () => CheckHTTP(CS$<>8__locals0.host), <results>5__3, <done>5__4);
					SpawnCheck(2, () => CheckWSS(CS$<>8__locals0.host), <results>5__3, <done>5__4);
					<waited>5__5 = 0f;
					goto IL_0139;
				}
				photonStatusHUD.checking = false;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <CheckLoop>d__7 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public PhotonStatusHUD <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <CheckLoop>d__7(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Expected O, but got Unknown
				int num = <>1__state;
				PhotonStatusHUD photonStatusHUD = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					goto IL_0029;
				case 1:
					<>1__state = -1;
					break;
				case 2:
					{
						<>1__state = -1;
						goto IL_0029;
					}
					IL_0029:
					if (!photonStatusHUD.checking)
					{
						<>2__current = ((MonoBehaviour)photonStatusHUD).StartCoroutine(photonStatusHUD.CheckAll());
						<>1__state = 1;
						return true;
					}
					break;
				}
				<>2__current = (object)new WaitForSeconds(30f);
				<>1__state = 2;
				return true;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static readonly (string key, string host)[] Servers = new(string, string)[4]
		{
			("ns", "ns.photonengine.io"),
			("eu", "ns-eu.photonengine.io"),
			("us", "ns-us.photonengine.io"),
			("jp", "ns-jp.photonengine.io")
		};

		private bool?[,] statuses;

		private TextMeshProUGUI label;

		private bool checking;

		private static readonly string[] CheckLabels = new string[3] { "IP", "HTTP", "WSS" };

		private void Awake()
		{
			label = ((Component)this).GetComponent<TextMeshProUGUI>();
			statuses = new bool?[Servers.Length, 3];
			TextMeshProUGUI obj = label;
			((TMP_Text)obj).fontSize = ((TMP_Text)obj).fontSize * 0.75f;
		}

		private void Start()
		{
			UpdateText();
			((MonoBehaviour)this).StartCoroutine(CheckLoop());
		}

		[IteratorStateMachine(typeof(<CheckLoop>d__7))]
		private IEnumerator CheckLoop()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CheckLoop>d__7(0)
			{
				<>4__this = this
			};
		}

		[IteratorStateMachine(typeof(<CheckAll>d__8))]
		private IEnumerator CheckAll()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CheckAll>d__8(0)
			{
				<>4__this = this
			};
		}

		private static void SpawnCheck(int idx, Func<bool> check, bool[] results, bool[] done)
		{
			Thread thread = new Thread((ThreadStart)delegate
			{
				try
				{
					results[idx] = check();
				}
				catch
				{
					results[idx] = false;
				}
				finally
				{
					done[idx] = true;
				}
			});
			thread.IsBackground = true;
			thread.Start();
		}

		private static bool CheckIP(string host)
		{
			IPAddress[] hostAddresses = Dns.GetHostAddresses(host);
			if (hostAddresses != null)
			{
				return hostAddresses.Length != 0;
			}
			return false;
		}

		private static bool CheckHTTP(string host)
		{
			using TcpClient tcpClient = new TcpClient();
			IAsyncResult asyncResult = tcpClient.BeginConnect(host, 80, null, null);
			if (!asyncResult.AsyncWaitHandle.WaitOne(3000))
			{
				return false;
			}
			tcpClient.EndConnect(asyncResult);
			return tcpClient.Connected;
		}

		private static bool CheckWSS(string host)
		{
			using TcpClient tcpClient = new TcpClient();
			IAsyncResult asyncResult = tcpClient.BeginConnect(host, 443, null, null);
			if (!asyncResult.AsyncWaitHandle.WaitOne(3000))
			{
				return false;
			}
			tcpClient.EndConnect(asyncResult);
			using SslStream sslStream = new SslStream(tcpClient.GetStream(), leaveInnerStreamOpen: false, (object _, X509Certificate __, X509Chain ___, SslPolicyErrors ____) => true);
			sslStream.AuthenticateAsClient(host);
			return true;
		}

		private void UpdateText()
		{
			if ((Object)(object)label == (Object)null)
			{
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("Photon (IP|HTTP|WSS): ");
			for (int i = 0; i < Servers.Length; i++)
			{
				stringBuilder.Append(Servers[i].key + " ");
				for (int j = 0; j < 3; j++)
				{
					bool? flag = statuses[i, j];
					string text = ((!flag.HasValue) ? "#ffff00" : (flag.Value ? "#00ff00" : "#ff4444"));
					string text2 = ((!flag.HasValue) ? "?" : (flag.Value ? "✓" : "✗"));
					stringBuilder.Append("<color=" + text + ">" + text2 + "</color>");
				}
				if (i < Servers.Length - 1)
				{
					stringBuilder.Append(", ");
				}
			}
			((TMP_Text)label).text = stringBuilder.ToString();
		}
	}
	[BepInPlugin("TFS_PhotonNetworkChecker", "TFS_PhotonNetworkChecker", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource PluginLogger;

		private static Harmony harmony;

		private void Awake()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			PluginLogger = ((BaseUnityPlugin)this).Logger;
			PluginLogger.LogInfo((object)"Plugin TFS_PhotonNetworkChecker loaded.");
			harmony = new Harmony("TFS_PhotonNetworkChecker");
			harmony.PatchAll();
		}
	}
}
namespace TFS_PhotonNetworkChecker.patches
{
	[HarmonyPatch(typeof(MenuPageMain))]
	internal class MenuPageMainPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		public static void InjectPhotonStatus(MenuPageMain __instance)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)__instance).transform.Find("Header");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.PluginLogger.LogWarning((object)"[PhotonNetworkChecker] 'Header' not found in MenuPageMain");
				return;
			}
			Transform val2 = val.Find("Build Name");
			if ((Object)(object)val2 == (Object)null)
			{
				Plugin.PluginLogger.LogWarning((object)"[PhotonNetworkChecker] 'Build Name' not found in Header");
			}
			else if (!((Object)(object)val.Find("Photon Status") != (Object)null))
			{
				GameObject obj = Object.Instantiate<GameObject>(((Component)val2).gameObject, val);
				((Object)obj).name = "Photon Status";
				RectTransform component = ((Component)val2).GetComponent<RectTransform>();
				RectTransform component2 = obj.GetComponent<RectTransform>();
				if ((Object)(object)component2 != (Object)null && (Object)(object)component != (Object)null)
				{
					component2.anchoredPosition = component.anchoredPosition + new Vector2(0f, -20f);
				}
				BuildName component3 = obj.GetComponent<BuildName>();
				if ((Object)(object)component3 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component3);
				}
				obj.AddComponent<PhotonStatusHUD>();
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}