using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using HarmonyLib; using Microsoft.CodeAnalysis; using Mirror; using Steamworks.Data; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Localization.Components; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("HostPauseMod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("HostPauseMod")] [assembly: AssemblyTitle("HostPauseMod")] [assembly: AssemblyVersion("1.0.0.0")] [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 HostPauseMod { [BepInPlugin("codex.superbattlegolf.hostpause", "Host Pause", "0.2.1")] public sealed class HostPausePlugin : BaseUnityPlugin { private sealed class RigidbodySnapshot { public Rigidbody Body; public bool IsKinematic; public bool UseGravity; public bool DetectCollisions; public Vector3 LinearVelocity; public Vector3 AngularVelocity; } [HarmonyPatch(typeof(PauseMenu), "Awake")] private static class PauseMenuAwakePatch { private static void Postfix(PauseMenu __instance) { instance?.AddPauseButton(__instance); } } [HarmonyPatch(typeof(PauseMenu), "OnEnable")] private static class PauseMenuOnEnablePatch { private static void Postfix(PauseMenu __instance) { if ((Object)(object)instance?.pauseButton != (Object)null) { RefreshPauseMenuButtonList(__instance); FitPauseMenuButtonStack(__instance); instance.RefreshPauseButton(); } } } [HarmonyPatch(typeof(BNetworkManager), "OnStartClient")] private static class NetworkStartClientPatch { private static void Postfix() { lastObservedLobbyPauseVersion = string.Empty; nextLobbyPollTime = 0f; } } [HarmonyPatch(typeof(BNetworkManager), "OnStopServer")] private static class NetworkStopServerPatch { private static void Prefix() { pendingRemotePause = false; PublishSteamLobbyPauseState(paused: false); ForceLocalResume(); } } [HarmonyPatch(typeof(BNetworkManager), "OnStopClient")] private static class NetworkStopClientPatch { private static void Prefix() { lastObservedLobbyPauseVersion = string.Empty; nextLobbyPollTime = 0f; pendingRemotePause = false; ForceLocalResume(); } } [HarmonyPatch(typeof(PlayerMovement), "Update")] private static class PlayerMovementUpdatePatch { private static bool Prefix() { return !isPaused; } } [HarmonyPatch(typeof(PlayerMovement), "FixedUpdate")] private static class PlayerMovementFixedUpdatePatch { private static bool Prefix() { return !isPaused; } } [HarmonyPatch(typeof(GolfBall), "UpdatePhysics")] private static class GolfBallUpdatePhysicsPatch { private static bool Prefix() { return !isPaused; } } [CompilerGenerated] private static class <>O { public static UnityAction <0>__TogglePauseFromPauseMenu; } private const string PluginGuid = "codex.superbattlegolf.hostpause"; private const string PluginName = "Host Pause"; private const string PluginVersion = "0.2.1"; private const string LobbyPauseStateKey = "codex_hostpause_state"; private const string LobbyPauseVersionKey = "codex_hostpause_version"; private static HostPausePlugin instance; private static bool isPaused; private static string lastObservedLobbyPauseVersion = string.Empty; private static float nextLobbyPollTime; private static bool pendingRemotePause; private static bool pauseMenuStackAdjusted; private static Vector3 pauseMenuOriginalScale; private static Vector2 pauseMenuOriginalAnchoredPosition; private static bool pauseBannerApplied; private static bool aheadBannerWasVisibleBeforePause; private static readonly List frozenRigidbodies = new List(); private static readonly Dictionary pauseBannerOriginalTexts = new Dictionary(); private static readonly List pauseBannerDisabledLocalizers = new List(); private Harmony harmony; private Button pauseButton; private TMP_Text pauseButtonLabel; private void Awake() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown instance = this; harmony = new Harmony("codex.superbattlegolf.hostpause"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Host Pause 0.2.1 loaded."); } private void OnDestroy() { ForceLocalResume(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if (instance == this) { instance = null; } } private void Update() { if (isPaused) { if (!CanApplyPauseState()) { ForceLocalResume(); return; } MaintainFrozenRigidbodies(); ShowPauseBanner(); } PollSteamLobbyPauseState(); TryApplyPendingRemotePause(); if (isPaused && !NetworkServer.active && !NetworkClient.active) { ForceLocalResume(); } RefreshPauseButton(); } private static void PollSteamLobbyPauseState() { if (NetworkServer.active || !NetworkClient.active || !NetworkClient.isConnected || NetworkClient.connection == null || !((NetworkConnection)NetworkClient.connection).isAuthenticated || !CanApplyPauseState() || Time.unscaledTime < nextLobbyPollTime) { return; } nextLobbyPollTime = Time.unscaledTime + 0.5f; Lobby val = default(Lobby); if (BNetworkManager.TryGetSteamLobby(ref val)) { string data = ((Lobby)(ref val)).GetData("codex_hostpause_version"); if (!string.IsNullOrEmpty(data) && !(data == lastObservedLobbyPauseVersion)) { lastObservedLobbyPauseVersion = data; ApplyRemotePause(((Lobby)(ref val)).GetData("codex_hostpause_state") == "1"); } } } private static void TogglePauseFromPauseMenu() { if (!NetworkServer.active) { return; } bool flag = !isPaused; if (flag && !CanApplyPauseState()) { HostPausePlugin hostPausePlugin = instance; if (hostPausePlugin != null) { ((BaseUnityPlugin)hostPausePlugin).Logger.LogWarning((object)"Ignoring pause request because the game is not in a playable match state."); } } else { PauseMenu.Unpause(); ApplyPauseLocal(flag); PublishSteamLobbyPauseState(flag); } } private static void PublishSteamLobbyPauseState(bool paused) { Lobby val = default(Lobby); if (NetworkServer.active && BNetworkManager.TryGetSteamLobby(ref val)) { ((Lobby)(ref val)).SetData("codex_hostpause_state", paused ? "1" : "0"); ((Lobby)(ref val)).SetData("codex_hostpause_version", Time.unscaledTime.ToString("R")); } } private static void ApplyPauseLocal(bool paused) { if (paused) { if (!CanApplyPauseState()) { pendingRemotePause = true; ForceLocalResume(); return; } if (!isPaused) { FreezeRigidbodies(); ShowPauseBanner(); } isPaused = true; } else { pendingRemotePause = false; isPaused = false; RestoreRigidbodies(); RestorePauseBanner(); } instance?.RefreshPauseButton(); } private static void ApplyRemotePause(bool paused) { if (!paused) { pendingRemotePause = false; ApplyPauseLocal(paused: false); } else if (!CanApplyPauseState()) { pendingRemotePause = true; ForceLocalResume(); } else { pendingRemotePause = false; ApplyPauseLocal(paused: true); } } private static void TryApplyPendingRemotePause() { if (pendingRemotePause && !isPaused && CanApplyPauseState()) { pendingRemotePause = false; ApplyPauseLocal(paused: true); } } private static void ForceLocalResume() { isPaused = false; RestoreRigidbodies(); RestorePauseBanner(); instance?.RefreshPauseButton(); } private static bool CanApplyPauseState() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 if (!NetworkServer.active && (!NetworkClient.active || NetworkClient.connection == null || !((NetworkConnection)NetworkClient.connection).isAuthenticated)) { return false; } if (!SingletonBehaviour.HasInstance) { return false; } if ((Object)(object)GameManager.LocalPlayerInfo == (Object)null || (Object)(object)GameManager.LocalPlayerMovement == (Object)null) { return false; } MatchState matchState = CourseManager.MatchState; if ((int)matchState >= 1) { return (int)matchState < 6; } return false; } private static void ShowPauseBanner() { AheadOfBallMessage aheadOfBallMessage = GetAheadOfBallMessage(); if ((Object)(object)aheadOfBallMessage == (Object)null) { return; } if (!pauseBannerApplied) { aheadBannerWasVisibleBeforePause = GetAheadBannerVisible(aheadOfBallMessage); pauseBannerOriginalTexts.Clear(); pauseBannerDisabledLocalizers.Clear(); LocalizeStringEvent[] componentsInChildren = ((Component)aheadOfBallMessage).GetComponentsInChildren(true); foreach (LocalizeStringEvent val in componentsInChildren) { if (((Behaviour)val).enabled) { ((Behaviour)val).enabled = false; pauseBannerDisabledLocalizers.Add(val); } } TMP_Text[] componentsInChildren2 = ((Component)aheadOfBallMessage).GetComponentsInChildren(true); foreach (TMP_Text val2 in componentsInChildren2) { pauseBannerOriginalTexts[val2] = val2.text; val2.text = "Game Paused"; } pauseBannerApplied = true; } else { foreach (TMP_Text key in pauseBannerOriginalTexts.Keys) { if ((Object)(object)key != (Object)null) { key.text = "Game Paused"; } } } AheadOfBallMessage.Show(); } private static void RestorePauseBanner() { if (!pauseBannerApplied) { return; } foreach (KeyValuePair pauseBannerOriginalText in pauseBannerOriginalTexts) { if ((Object)(object)pauseBannerOriginalText.Key != (Object)null) { pauseBannerOriginalText.Key.text = pauseBannerOriginalText.Value; } } foreach (LocalizeStringEvent pauseBannerDisabledLocalizer in pauseBannerDisabledLocalizers) { if ((Object)(object)pauseBannerDisabledLocalizer != (Object)null) { ((Behaviour)pauseBannerDisabledLocalizer).enabled = true; } } pauseBannerOriginalTexts.Clear(); pauseBannerDisabledLocalizers.Clear(); pauseBannerApplied = false; if (aheadBannerWasVisibleBeforePause) { AheadOfBallMessage.Show(); } else { AheadOfBallMessage.Hide(); } } private static AheadOfBallMessage GetAheadOfBallMessage() { if (SingletonBehaviour.HasInstance) { return SingletonBehaviour.Instance; } return Object.FindFirstObjectByType((FindObjectsInactive)1); } private static bool GetAheadBannerVisible(AheadOfBallMessage banner) { object obj = AccessTools.Field(typeof(AheadOfBallMessage), "isVisible")?.GetValue(banner); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static void FreezeRigidbodies() { //IL_0059: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) frozenRigidbodies.Clear(); Rigidbody[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Rigidbody val in array) { if (!((Object)(object)val == (Object)null)) { frozenRigidbodies.Add(new RigidbodySnapshot { Body = val, IsKinematic = val.isKinematic, UseGravity = val.useGravity, DetectCollisions = val.detectCollisions, LinearVelocity = val.linearVelocity, AngularVelocity = val.angularVelocity }); FreezeRigidbody(val); } } } private static void MaintainFrozenRigidbodies() { foreach (RigidbodySnapshot frozenRigidbody in frozenRigidbodies) { if ((Object)(object)frozenRigidbody.Body != (Object)null) { FreezeRigidbody(frozenRigidbody.Body); } } } private static void FreezeRigidbody(Rigidbody body) { //IL_0001: 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) body.linearVelocity = Vector3.zero; body.angularVelocity = Vector3.zero; body.isKinematic = true; } private static void RestoreRigidbodies() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) foreach (RigidbodySnapshot frozenRigidbody in frozenRigidbodies) { Rigidbody body = frozenRigidbody.Body; if (!((Object)(object)body == (Object)null)) { body.useGravity = frozenRigidbody.UseGravity; body.detectCollisions = frozenRigidbody.DetectCollisions; body.isKinematic = frozenRigidbody.IsKinematic; if (!body.isKinematic) { body.linearVelocity = frozenRigidbody.LinearVelocity; body.angularVelocity = frozenRigidbody.AngularVelocity; } } } frozenRigidbodies.Clear(); } private void AddPauseButton(PauseMenu pauseMenu) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown if ((Object)(object)pauseMenu == (Object)null || (Object)(object)pauseMenu.menuButtonContainer == (Object)null || (Object)(object)pauseButton != (Object)null) { return; } Button val = FindPauseButtonTemplate(pauseMenu); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not find a pause menu button to clone for Host Pause."); return; } GameObject val2 = Object.Instantiate(((Component)val).gameObject, ((Component)val).transform.parent); ((Object)val2).name = "HostPauseButton"; val2.transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex() + 1); LocalizeStringEvent[] componentsInChildren = val2.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } pauseButton = val2.GetComponent