Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CancelJoiningLobby v1.0.0
BepInEx/plugins/ZaboomafooW-CancelJoiningLobby-v1.0.0.dll
Decompiled 8 hours agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using CancelJoiningLobby.Controllers; using HarmonyLib; using Microsoft.CodeAnalysis; using Steamworks; using TMPro; using Unity.Netcode; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.UI; [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("CancelJoiningLobby")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("CancelJoiningLobby")] [assembly: AssemblyTitle("CancelJoiningLobby")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CancelJoiningLobby { [BepInPlugin("ZaboomafooW.CancelJoiningLobby", "Cancel Joining Lobby", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "ZaboomafooW.CancelJoiningLobby"; public const string PluginName = "Cancel Joining Lobby"; public const string PluginVersion = "1.0.0"; private Harmony _harmony; internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; if (ConnectionCancellationController.Initialize()) { _harmony = new Harmony("ZaboomafooW.CancelJoiningLobby"); _harmony.PatchAll(); Log.LogInfo((object)"[CancelJoiningLobby] Loaded v1.0.0"); } } private void OnApplicationQuit() { ConnectionCancellationController.Cleanup(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; Log = null; } } } namespace CancelJoiningLobby.Patches { [HarmonyPatch(typeof(LobbySlot), "JoinLobbyAfterVerifying")] internal static class JoinLobbyAfterVerifyingPatch { private static void Prefix() { ConnectionCancellationController.CaptureJoinAttempt(); } } [HarmonyPatch(typeof(MenuManager), "SetLoadingScreen")] internal static class SetLoadingScreenPatch { private static void Postfix(bool isLoading) { if (!isLoading) { ConnectionCancellationController.OnLoadingScreenClosed(); } } } [HarmonyPatch(typeof(GameNetworkManager), "StartClient")] internal static class StartClientPatch { private static void Prefix() { ConnectionCancellationController.BeginContactingServer(); } private static void Postfix() { ConnectionCancellationController.CompleteStartClient(); } } } namespace CancelJoiningLobby.Controllers { internal static class CancelButtonController { private const string ButtonObjectName = "CancelJoiningLobby.CancelButton"; private const string ButtonText = "[ Cancel ]"; private static GameObject _cancelButtonObject; private static bool _hookLogged; internal static bool Show(MenuManager menuManager) { if (!EnsureButton(menuManager)) { return false; } _cancelButtonObject.SetActive(true); return true; } internal static void Hide() { if ((Object)(object)_cancelButtonObject != (Object)null) { _cancelButtonObject.SetActive(false); } } internal static void Cleanup() { if (!((Object)(object)_cancelButtonObject == (Object)null)) { Object.Destroy((Object)(object)_cancelButtonObject); _cancelButtonObject = null; _hookLogged = false; } } private static bool EnsureButton(MenuManager menuManager) { //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_0221: 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_026d: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)menuManager == (Object)null || (Object)(object)menuManager.loadingText == (Object)null || (Object)(object)menuManager.loadingScreen == (Object)null || !menuManager.loadingScreen.activeInHierarchy || !((Component)menuManager.loadingText).gameObject.activeInHierarchy) { Plugin.Log.LogError((object)"[CancelJoiningLobby] Loading screen UI was unavailable; cancel button was not created."); return false; } if ((Object)(object)_cancelButtonObject != (Object)null && (Object)(object)_cancelButtonObject.transform.parent != (Object)(object)((TMP_Text)menuManager.loadingText).transform) { Object.Destroy((Object)(object)_cancelButtonObject); _cancelButtonObject = null; } if ((Object)(object)_cancelButtonObject != (Object)null) { return true; } Canvas canvas = ((Graphic)menuManager.loadingText).canvas; if ((Object)(object)canvas == (Object)null) { Plugin.Log.LogError((object)"[CancelJoiningLobby] Loading screen canvas was unavailable; cancel button was not created."); return false; } GameObject val = new GameObject("CancelJoiningLobby.CancelButton", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(CancelButtonInputHandler) }); val.transform.SetParent(((TMP_Text)menuManager.loadingText).transform, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 0f); component.anchorMax = new Vector2(0.5f, 0f); component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = Vector2.zero; Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = Color.clear; ((Graphic)component2).raycastTarget = false; GameObject val2 = new GameObject("CancelJoiningLobby.CancelButton.Text", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(TextMeshProUGUI) }); val2.transform.SetParent(val.transform, false); TextMeshProUGUI loadingText = menuManager.loadingText; TextMeshProUGUI component3 = val2.GetComponent<TextMeshProUGUI>(); ((TMP_Text)component3).text = "[ Cancel ]"; ((TMP_Text)component3).font = ((TMP_Text)loadingText).font; ((TMP_Text)component3).fontSharedMaterial = ((TMP_Text)loadingText).fontSharedMaterial; ((TMP_Text)component3).fontSize = ((TMP_Text)loadingText).fontSize; ((TMP_Text)component3).fontStyle = ((TMP_Text)loadingText).fontStyle; ((Graphic)component3).color = ((Graphic)loadingText).color; ((TMP_Text)component3).alignment = (TextAlignmentOptions)514; ((TMP_Text)component3).enableWordWrapping = false; ((Graphic)component3).raycastTarget = false; ((TMP_Text)component3).ForceMeshUpdate(false, false); component.sizeDelta = new Vector2(((TMP_Text)component3).preferredWidth, ((TMP_Text)component3).preferredHeight); RectTransform component4 = val2.GetComponent<RectTransform>(); component4.anchorMin = Vector2.zero; component4.anchorMax = Vector2.one; component4.offsetMin = Vector2.zero; component4.offsetMax = Vector2.zero; val.GetComponent<CancelButtonInputHandler>().Initialize(component, canvas, component2, component3, ((Graphic)loadingText).color); _cancelButtonObject = val; _cancelButtonObject.SetActive(false); if (!_hookLogged) { _hookLogged = true; Plugin.Log.LogInfo((object)"[CancelJoiningLobby] Hook succeeded: cancel input attached to the v81 loading screen."); } return true; } } internal sealed class CancelButtonInputHandler : MonoBehaviour { private RectTransform _buttonRect; private Canvas _canvas; private Image _background; private TextMeshProUGUI _text; private Color _normalTextColor; private bool _isHighlighted; internal void Initialize(RectTransform buttonRect, Canvas canvas, Image background, TextMeshProUGUI text, Color normalTextColor) { //IL_001e: 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) _buttonRect = buttonRect; _canvas = canvas; _background = background; _text = text; _normalTextColor = normalTextColor; SetHighlighted(highlighted: false); } private void Update() { //IL_0062: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (Keyboard.current != null && ((ButtonControl)Keyboard.current.escapeKey).wasPressedThisFrame) { Plugin.Log.LogInfo((object)"[CancelJoiningLobby] Cancel requested with Escape."); ConnectionCancellationController.CancelConnectionAttempt(); return; } if ((Object)(object)_buttonRect == (Object)null || (Object)(object)_canvas == (Object)null || Mouse.current == null) { SetHighlighted(highlighted: false); return; } Vector2 val = ((InputControl<Vector2>)(object)((Pointer)Mouse.current).position).ReadValue(); Camera val2 = (((int)_canvas.renderMode == 0) ? null : _canvas.worldCamera); bool flag = RectTransformUtility.RectangleContainsScreenPoint(_buttonRect, val, val2); SetHighlighted(flag); if (flag && Mouse.current.leftButton.wasReleasedThisFrame) { Plugin.Log.LogInfo((object)"[CancelJoiningLobby] Cancel clicked."); ConnectionCancellationController.CancelConnectionAttempt(); } } private void OnDisable() { SetHighlighted(highlighted: false); } private void SetHighlighted(bool highlighted) { //IL_003e: 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_0059: 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) if (!((Object)(object)_background == (Object)null) && !((Object)(object)_text == (Object)null) && _isHighlighted != highlighted) { _isHighlighted = highlighted; ((Graphic)_background).color = (highlighted ? _normalTextColor : Color.clear); ((Graphic)_text).color = (highlighted ? Color.black : _normalTextColor); } } } internal static class ConnectionCancellationController { [CompilerGenerated] private static class <>O { public static TransportEventDelegate <0>__OnTransportEvent; public static Action<bool> <1>__OnClientStopped; } private const BindingFlags InstanceNonPublic = BindingFlags.Instance | BindingFlags.NonPublic; private static MethodInfo _setInstanceValuesBackToDefaultMethod; private static NetworkTransport _observedTransport; private static NetworkManager _shutdownNetworkManager; private static MenuManager _capturedMenu; private static GameObject _previouslySelectedObject; private static bool _joinAttemptCaptured; private static bool _contactingServer; private static bool _cancellationInProgress; private static bool _originalMenuButtonsActive; private static bool _originalServerListActive; private static bool _originalLoadingScreenActive; private static float _originalMenuAudioVolume; private static bool _menuAudioCaptured; internal static bool Initialize() { try { _setInstanceValuesBackToDefaultMethod = typeof(GameNetworkManager).GetMethod("SetInstanceValuesBackToDefault", BindingFlags.Instance | BindingFlags.NonPublic); } catch (Exception ex) { Plugin.Log.LogError((object)("[CancelJoiningLobby] Failed to resolve verified vanilla connection cleanup method: " + ex)); return false; } if (_setInstanceValuesBackToDefaultMethod == null) { Plugin.Log.LogError((object)"[CancelJoiningLobby] Verified vanilla connection cleanup method was not found."); return false; } return true; } internal static void CaptureJoinAttempt() { if (_cancellationInProgress) { return; } GameNetworkManager instance = GameNetworkManager.Instance; if ((Object)(object)instance == (Object)null || instance.disableSteam) { ClearJoinAttempt(); return; } MenuManager val = Object.FindObjectOfType<MenuManager>(); if ((Object)(object)val == (Object)null || (Object)(object)val.menuButtons == (Object)null || (Object)(object)val.serverListUIContainer == (Object)null || (Object)(object)val.loadingScreen == (Object)null || !val.serverListUIContainer.activeSelf) { ClearJoinAttempt(); return; } _capturedMenu = val; _originalMenuButtonsActive = val.menuButtons.activeSelf; _originalServerListActive = val.serverListUIContainer.activeSelf; _originalLoadingScreenActive = val.loadingScreen.activeSelf; _menuAudioCaptured = (Object)(object)val.MenuAudio != (Object)null; if (_menuAudioCaptured) { _originalMenuAudioVolume = val.MenuAudio.volume; } _previouslySelectedObject = (((Object)(object)EventSystem.current != (Object)null) ? EventSystem.current.currentSelectedGameObject : null); _joinAttemptCaptured = true; _contactingServer = false; CancelButtonController.Hide(); } internal static void BeginContactingServer() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown if (!_joinAttemptCaptured || _cancellationInProgress) { return; } NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)singleton == (Object)null || singleton.IsServer || singleton.IsHost) { ClearJoinAttempt(); return; } NetworkTransport val = ((singleton.NetworkConfig != null) ? singleton.NetworkConfig.NetworkTransport : null); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"[CancelJoiningLobby] Network transport was unavailable when the server connection attempt started."); ClearJoinAttempt(); return; } UnsubscribeTransport(); _observedTransport = val; NetworkTransport observedTransport = _observedTransport; object obj = <>O.<0>__OnTransportEvent; if (obj == null) { TransportEventDelegate val2 = OnTransportEvent; <>O.<0>__OnTransportEvent = val2; obj = (object)val2; } observedTransport.OnTransportEvent += (TransportEventDelegate)obj; _contactingServer = true; } internal static void CompleteStartClient() { if (_contactingServer && _joinAttemptCaptured && !_cancellationInProgress) { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsListening || !singleton.IsClient) { ClearJoinAttempt(); } else if (!CancelButtonController.Show(_capturedMenu)) { ClearJoinAttempt(); } } } internal static void OnLoadingScreenClosed() { if (!_cancellationInProgress) { ClearJoinAttempt(); } } internal static void CancelConnectionAttempt() { if (_contactingServer && _joinAttemptCaptured && !_cancellationInProgress) { GameNetworkManager instance = GameNetworkManager.Instance; NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)instance == (Object)null || (Object)(object)singleton == (Object)null || !singleton.IsListening || !singleton.IsClient) { ClearJoinAttempt(); return; } if (!ResetGameNetworkManagerState(instance)) { Plugin.Log.LogError((object)"[CancelJoiningLobby] Cancellation was aborted because vanilla connection state could not be reset safely."); return; } _cancellationInProgress = true; _contactingServer = false; CancelButtonController.Hide(); UnsubscribeTransport(); instance.localClientWaitingForApproval = false; instance.LeaveCurrentSteamLobby(); instance.steamLobbyName = SteamClient.Name; UnsubscribeClientStopped(); _shutdownNetworkManager = singleton; _shutdownNetworkManager.OnClientStopped += OnClientStopped; _shutdownNetworkManager.Shutdown(true); Plugin.Log.LogInfo((object)"[CancelJoiningLobby] Cancelled server connection attempt; Netcode shutdown started."); } } internal static void Cleanup() { UnsubscribeTransport(); UnsubscribeClientStopped(); CancelButtonController.Cleanup(); ClearCapturedState(); _setInstanceValuesBackToDefaultMethod = null; _cancellationInProgress = false; } private static void OnTransportEvent(NetworkEvent eventType, ulong clientId, ArraySegment<byte> payload, float receiveTime) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 if (_contactingServer && !_cancellationInProgress) { if ((int)eventType == 1) { ClearJoinAttempt(); } else if ((int)eventType == 2 || (int)eventType == 3) { ClearJoinAttempt(); } } } private static void OnClientStopped(bool wasServer) { UnsubscribeClientStopped(); GameNetworkManager instance = GameNetworkManager.Instance; if ((Object)(object)instance != (Object)null) { instance.disconnectReason = 0; instance.disconnectionReasonMessage = string.Empty; } RestoreCapturedMenuState(); RefreshServerList(); _cancellationInProgress = false; ClearCapturedState(); Plugin.Log.LogInfo((object)"[CancelJoiningLobby] Returned to the server browser after cancellation."); } private static void RefreshServerList() { SteamLobbyManager val = Object.FindObjectOfType<SteamLobbyManager>(); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"[CancelJoiningLobby] Server list manager was unavailable after cancellation; refresh could not be requested."); return; } val.LoadServerList(); Plugin.Log.LogInfo((object)"[CancelJoiningLobby] Server list refresh requested after cancellation."); } private static bool ResetGameNetworkManagerState(GameNetworkManager gameNetworkManager) { if (_setInstanceValuesBackToDefaultMethod == null) { Plugin.Log.LogError((object)"[CancelJoiningLobby] Verified vanilla connection cleanup method is unavailable."); return false; } try { _setInstanceValuesBackToDefaultMethod.Invoke(gameNetworkManager, null); return true; } catch (TargetInvocationException ex) { Exception? obj = ex.InnerException ?? ex; Plugin.Log.LogError((object)("[CancelJoiningLobby] Vanilla connection cleanup failed: " + obj)); return false; } catch (Exception ex2) { Plugin.Log.LogError((object)("[CancelJoiningLobby] Vanilla connection cleanup failed: " + ex2)); return false; } } private static void RestoreCapturedMenuState() { if ((Object)(object)_capturedMenu == (Object)null) { Plugin.Log.LogError((object)"[CancelJoiningLobby] Captured menu was unavailable after cancellation; UI state could not be restored."); return; } if ((Object)(object)_capturedMenu.loadingScreen != (Object)null) { _capturedMenu.loadingScreen.SetActive(_originalLoadingScreenActive); } if ((Object)(object)_capturedMenu.menuButtons != (Object)null) { _capturedMenu.menuButtons.SetActive(_originalMenuButtonsActive); } if ((Object)(object)_capturedMenu.serverListUIContainer != (Object)null) { _capturedMenu.serverListUIContainer.SetActive(_originalServerListActive); } if (_menuAudioCaptured && (Object)(object)_capturedMenu.MenuAudio != (Object)null) { _capturedMenu.MenuAudio.volume = _originalMenuAudioVolume; } if ((Object)(object)EventSystem.current != (Object)null && (Object)(object)_previouslySelectedObject != (Object)null && _previouslySelectedObject.activeInHierarchy) { EventSystem.current.SetSelectedGameObject(_previouslySelectedObject); } } private static void ClearJoinAttempt() { _contactingServer = false; CancelButtonController.Hide(); UnsubscribeTransport(); ClearCapturedState(); } private static void ClearCapturedState() { _joinAttemptCaptured = false; _capturedMenu = null; _previouslySelectedObject = null; _menuAudioCaptured = false; _originalMenuAudioVolume = 0f; } private static void UnsubscribeTransport() { //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_002e: Expected O, but got Unknown if (!((Object)(object)_observedTransport == (Object)null)) { NetworkTransport observedTransport = _observedTransport; object obj = <>O.<0>__OnTransportEvent; if (obj == null) { TransportEventDelegate val = OnTransportEvent; <>O.<0>__OnTransportEvent = val; obj = (object)val; } observedTransport.OnTransportEvent -= (TransportEventDelegate)obj; _observedTransport = null; } } private static void UnsubscribeClientStopped() { if (!((Object)(object)_shutdownNetworkManager == (Object)null)) { _shutdownNetworkManager.OnClientStopped -= OnClientStopped; _shutdownNetworkManager = null; } } } }