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 b__0() { return CheckIP(host); } internal bool b__1() { return CheckHTTP(host); } internal bool b__2() { return CheckWSS(host); } } [CompilerGenerated] private sealed class d__8 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PhotonStatusHUD <>4__this; private int 5__2; private bool[] 5__3; private bool[] 5__4; private float 5__5; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__3 = null; 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(); 5__2 = 0; goto IL_01c9; IL_0139: if ((!5__4[0] || !5__4[1] || !5__4[2]) && 5__5 < 8f) { 5__5 += Time.unscaledDeltaTime; <>2__current = null; <>1__state = 1; return true; } for (int k = 0; k < 3; k++) { photonStatusHUD.statuses[5__2, k] = 5__4[k] && 5__3[k]; } photonStatusHUD.UpdateText(); 5__3 = null; 5__4 = null; 5__2++; goto IL_01c9; IL_01c9: if (5__2 < Servers.Length) { <>c__DisplayClass8_0 CS$<>8__locals0 = new <>c__DisplayClass8_0 { host = Servers[5__2].host }; 5__3 = new bool[3]; 5__4 = new bool[3]; SpawnCheck(0, () => CheckIP(CS$<>8__locals0.host), 5__3, 5__4); SpawnCheck(1, () => CheckHTTP(CS$<>8__locals0.host), 5__3, 5__4); SpawnCheck(2, () => CheckWSS(CS$<>8__locals0.host), 5__3, 5__4); 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 d__7 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PhotonStatusHUD <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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(); 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(d__7))] private IEnumerator CheckLoop() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__7(0) { <>4__this = this }; } [IteratorStateMachine(typeof(d__8))] private IEnumerator CheckAll() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__8(0) { <>4__this = this }; } private static void SpawnCheck(int idx, Func 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("" + text2 + ""); } 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(((Component)val2).gameObject, val); ((Object)obj).name = "Photon Status"; RectTransform component = ((Component)val2).GetComponent(); RectTransform component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component != (Object)null) { component2.anchoredPosition = component.anchoredPosition + new Vector2(0f, -20f); } BuildName component3 = obj.GetComponent(); if ((Object)(object)component3 != (Object)null) { Object.DestroyImmediate((Object)(object)component3); } obj.AddComponent(); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }