Decompiled source of Host Pause v0.2.8

BepInEx\plugins\HostPauseMod.dll

Decompiled a month ago
using System;
using System.Collections;
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]
	[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 HostPauseMod
{
	[BepInPlugin("codex.superbattlegolf.hostpause", "Host Pause", "0.2.8")]
	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;
				lastObservedLobbyPauseState = "0";
				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;
				lastObservedLobbyPauseState = "0";
				nextLobbyPollTime = 0f;
				pendingRemotePause = false;
				ForceLocalResume();
			}
		}

		[HarmonyPatch(typeof(PlayerMovement), "Update")]
		private static class PlayerMovementUpdatePatch
		{
			private static bool Prefix()
			{
				return !ShouldBlockGameplay();
			}
		}

		[HarmonyPatch(typeof(PlayerMovement), "FixedUpdate")]
		private static class PlayerMovementFixedUpdatePatch
		{
			private static bool Prefix()
			{
				return !ShouldBlockGameplay();
			}
		}

		[HarmonyPatch(typeof(PlayerMovement), "CanMove")]
		private static class PlayerMovementCanMovePatch
		{
			private static void Postfix(ref bool __result)
			{
				if (ShouldBlockGameplay())
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(PlayerMovement), "CanJump")]
		private static class PlayerMovementCanJumpPatch
		{
			private static void Postfix(ref bool __result)
			{
				if (ShouldBlockGameplay())
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "Update")]
		private static class PlayerInputUpdatePatch
		{
			private static bool Prefix(PlayerInput __instance)
			{
				if (!ShouldBlockGameplay())
				{
					return true;
				}
				ClearPausedInput(__instance);
				return false;
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "StartChargingSwing")]
		private static class PlayerInputStartChargingSwingPatch
		{
			private static bool Prefix(PlayerInput __instance)
			{
				if (!ShouldBlockGameplay())
				{
					return true;
				}
				ClearPausedInput(__instance);
				return false;
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "FinishChargingSwing")]
		private static class PlayerInputFinishChargingSwingPatch
		{
			private static bool Prefix(PlayerInput __instance)
			{
				if (!ShouldBlockGameplay())
				{
					return true;
				}
				ClearPausedInput(__instance);
				return false;
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "UseItem")]
		private static class PlayerInputUseItemPatch
		{
			private static bool Prefix(PlayerInput __instance, ref bool __result)
			{
				if (!ShouldBlockGameplay())
				{
					return true;
				}
				ClearPausedInput(__instance);
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "Jump")]
		private static class PlayerInputJumpPatch
		{
			private static bool Prefix(PlayerInput __instance)
			{
				return AllowPausedInputAction(__instance);
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "Interact")]
		private static class PlayerInputInteractPatch
		{
			private static bool Prefix(PlayerInput __instance)
			{
				return AllowPausedInputAction(__instance);
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "DropItem")]
		private static class PlayerInputDropItemPatch
		{
			private static bool Prefix(PlayerInput __instance)
			{
				return AllowPausedInputAction(__instance);
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "Dive")]
		private static class PlayerInputDivePatch
		{
			private static bool Prefix(PlayerInput __instance)
			{
				return AllowPausedInputAction(__instance);
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "CycleSwingAngle")]
		private static class PlayerInputCycleSwingAnglePatch
		{
			private static bool Prefix(PlayerInput __instance)
			{
				return AllowPausedInputAction(__instance);
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "GolfCartJump")]
		private static class PlayerInputGolfCartJumpPatch
		{
			private static bool Prefix(PlayerInput __instance)
			{
				return AllowPausedInputAction(__instance);
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "GolfCartHonk")]
		private static class PlayerInputGolfCartHonkPatch
		{
			private static bool Prefix(PlayerInput __instance)
			{
				return AllowPausedInputAction(__instance);
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "ExitGolfCart")]
		private static class PlayerInputExitGolfCartPatch
		{
			private static bool Prefix(PlayerInput __instance)
			{
				return AllowPausedInputAction(__instance);
			}
		}

		[HarmonyPatch(typeof(PlayerInput), "DiveOutOfGolfCart")]
		private static class PlayerInputDiveOutOfGolfCartPatch
		{
			private static bool Prefix(PlayerInput __instance)
			{
				return AllowPausedInputAction(__instance);
			}
		}

		[HarmonyPatch(typeof(PlayerInfo), "SetIsAimingSwing")]
		private static class PlayerInfoSetIsAimingSwingPatch
		{
			private static bool Prefix(bool __0)
			{
				if (ShouldBlockGameplay())
				{
					return !__0;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(PlayerInfo), "SetIsAimingItem")]
		private static class PlayerInfoSetIsAimingItemPatch
		{
			private static bool Prefix(bool __0)
			{
				if (ShouldBlockGameplay())
				{
					return !__0;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(PlayerGolfer), "OnPlayerHitOwnBall")]
		private static class PlayerGolferOnPlayerHitOwnBallPatch
		{
			private static bool Prefix()
			{
				return !ShouldBlockGameplay();
			}
		}

		[HarmonyPatch(typeof(GolfBall), "OnWillApplyGolfSwingHitPhysics")]
		private static class GolfBallApplySwingPhysicsPatch
		{
			private static bool Prefix()
			{
				return !ShouldBlockGameplay();
			}
		}

		[HarmonyPatch(typeof(GolfBall), "UpdatePhysics")]
		private static class GolfBallUpdatePhysicsPatch
		{
			private static bool Prefix()
			{
				return !ShouldBlockGameplay();
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__TogglePauseFromPauseMenu;

			public static UnityAction <1>__ReturnToLobbyFromPauseMenu;
		}

		private const string PluginGuid = "codex.superbattlegolf.hostpause";

		private const string PluginName = "Host Pause";

		private const string PluginVersion = "0.2.8";

		private const string LobbyPauseStateKey = "codex_hostpause_state";

		private const string LobbyPauseVersionKey = "codex_hostpause_version";

		private const string PauseStatePaused = "1";

		private const string PauseStateRunning = "0";

		private const string PauseStateResumeCountdown = "2";

		private static HostPausePlugin instance;

		private static bool isPaused;

		private static string lastObservedLobbyPauseVersion = string.Empty;

		private static string lastObservedLobbyPauseState = "0";

		private static float nextLobbyPollTime;

		private static bool pendingRemotePause;

		private static bool isResumeCountdownActive;

		private static bool pauseMenuStackAdjusted;

		private static Vector3 pauseMenuOriginalScale;

		private static Vector2 pauseMenuOriginalAnchoredPosition;

		private static bool pauseBannerApplied;

		private static bool aheadBannerWasVisibleBeforePause;

		private static readonly List<RigidbodySnapshot> frozenRigidbodies = new List<RigidbodySnapshot>();

		private static readonly Dictionary<TMP_Text, string> pauseBannerOriginalTexts = new Dictionary<TMP_Text, string>();

		private static readonly List<LocalizeStringEvent> pauseBannerDisabledLocalizers = new List<LocalizeStringEvent>();

		private static readonly Dictionary<PlayerAnimatorIo, int> pauseDanceOriginalValues = new Dictionary<PlayerAnimatorIo, int>();

		private static GUIStyle pauseOverlayBoxStyle;

		private static GUIStyle pauseOverlayTitleStyle;

		private static GUIStyle pauseOverlayDetailStyle;

		private static Texture2D pauseOverlayTexture;

		private static FieldInfo animatorField;

		private static FieldInfo victoryDanceHashField;

		private static FieldInfo playerInputPlayerInfoField;

		private static FieldInfo playerInputHoldingAimSwingField;

		private static FieldInfo playerInputHoldingChargeSwingField;

		private Harmony harmony;

		private Button pauseButton;

		private TMP_Text pauseButtonLabel;

		private Button backToLobbyButton;

		private TMP_Text backToLobbyButtonLabel;

		private Coroutine resumeCountdownRoutine;

		private void Awake()
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			instance = this;
			animatorField = AccessTools.Field(typeof(PlayerAnimatorIo), "animator");
			victoryDanceHashField = AccessTools.Field(typeof(PlayerAnimatorIo), "victoryDanceHash");
			playerInputPlayerInfoField = AccessTools.Field(typeof(PlayerInput), "playerInfo");
			playerInputHoldingAimSwingField = AccessTools.Field(typeof(PlayerInput), "<IsHoldingAimSwing>k__BackingField");
			playerInputHoldingChargeSwingField = AccessTools.Field(typeof(PlayerInput), "<IsHoldingChargeSwing>k__BackingField");
			harmony = new Harmony("codex.superbattlegolf.hostpause");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Host Pause 0.2.8 loaded.");
		}

		private void OnDestroy()
		{
			ForceLocalResume();
			DestroyPauseOverlayStyles();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if (instance == this)
			{
				instance = null;
			}
		}

		private void OnGUI()
		{
			DrawPauseOverlay();
		}

		private void Update()
		{
			if (ShouldBlockGameplay())
			{
				if (!CanApplyPauseState())
				{
					ForceLocalResume();
					return;
				}
				MaintainFrozenRigidbodies();
				CancelPausedPlayerActions();
				if (!isResumeCountdownActive)
				{
					ShowPauseBanner();
					MaintainPauseDances();
				}
			}
			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 || Time.unscaledTime < nextLobbyPollTime)
			{
				return;
			}
			nextLobbyPollTime = Time.unscaledTime + 0.5f;
			Lobby val = default(Lobby);
			if (!BNetworkManager.TryGetSteamLobby(ref val))
			{
				return;
			}
			string data = ((Lobby)(ref val)).GetData("codex_hostpause_version");
			string data2 = ((Lobby)(ref val)).GetData("codex_hostpause_state");
			if (!string.IsNullOrEmpty(data))
			{
				bool flag = data != lastObservedLobbyPauseVersion;
				lastObservedLobbyPauseVersion = data;
				lastObservedLobbyPauseState = data2;
				if (flag || ShouldReapplyObservedPauseState(data2))
				{
					ApplyRemotePauseState(data2);
				}
			}
		}

		private static bool ShouldReapplyObservedPauseState(string state)
		{
			if (state == "1")
			{
				if (ShouldBlockGameplay() && !pendingRemotePause)
				{
					return isResumeCountdownActive;
				}
				return true;
			}
			if (state == "2")
			{
				if (isPaused)
				{
					return !isResumeCountdownActive;
				}
				return false;
			}
			if (!isPaused && !pendingRemotePause)
			{
				return isResumeCountdownActive;
			}
			return true;
		}

		private static void TogglePauseFromPauseMenu()
		{
			if (!NetworkServer.active)
			{
				return;
			}
			bool flag = !ShouldBlockGameplay();
			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.");
				}
				return;
			}
			PauseMenu.Unpause();
			if (flag)
			{
				ApplyPauseLocal(paused: true);
				PublishSteamLobbyPauseState("1");
			}
			else
			{
				BeginResumeCountdownLocal();
				PublishSteamLobbyPauseState("2");
			}
		}

		private static void ReturnToLobbyFromPauseMenu()
		{
			//IL_0008: 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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			if (!NetworkServer.active)
			{
				return;
			}
			MatchState matchState = CourseManager.MatchState;
			if ((int)matchState < 1 || (int)matchState > 6)
			{
				HostPausePlugin hostPausePlugin = instance;
				if (hostPausePlugin != null)
				{
					((BaseUnityPlugin)hostPausePlugin).Logger.LogWarning((object)"Ignoring Back to Lobby request because no course is currently active.");
				}
				return;
			}
			PauseMenu.Unpause();
			PublishSteamLobbyPauseState("0");
			ForceLocalResume();
			CourseManager.EndCourse();
			HostPausePlugin hostPausePlugin2 = instance;
			if (hostPausePlugin2 != null)
			{
				((BaseUnityPlugin)hostPausePlugin2).Logger.LogInfo((object)"Host requested return to lobby through the native course end flow.");
			}
		}

		private static void PublishSteamLobbyPauseState(bool paused)
		{
			PublishSteamLobbyPauseState(paused ? "1" : "0");
		}

		private static void PublishSteamLobbyPauseState(string state)
		{
			Lobby val = default(Lobby);
			if (NetworkServer.active && BNetworkManager.TryGetSteamLobby(ref val))
			{
				((Lobby)(ref val)).SetData("codex_hostpause_state", state);
				((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 (!ShouldBlockGameplay())
				{
					FreezeRigidbodies();
					CancelPausedPlayerActions();
					ShowPauseBanner();
					ApplyPauseDances();
				}
				else if (isResumeCountdownActive)
				{
					instance?.StopResumeCountdown();
					CancelPausedPlayerActions();
					ShowPauseBanner();
					ApplyPauseDances();
				}
				isPaused = true;
			}
			else
			{
				instance?.StopResumeCountdown();
				pendingRemotePause = false;
				isResumeCountdownActive = false;
				isPaused = false;
				RestorePauseDances();
				RestoreRigidbodies();
				RestorePauseBanner();
			}
			instance?.RefreshPauseButton();
		}

		private static void BeginResumeCountdownLocal()
		{
			if (!ShouldBlockGameplay())
			{
				ApplyPauseLocal(paused: false);
			}
			else if (!CanApplyPauseState())
			{
				ApplyPauseLocal(paused: false);
			}
			else
			{
				instance?.StartResumeCountdown();
			}
		}

		private void StartResumeCountdown()
		{
			StopResumeCountdown();
			resumeCountdownRoutine = ((MonoBehaviour)this).StartCoroutine(ResumeCountdownRoutine());
		}

		private void StopResumeCountdown()
		{
			if (resumeCountdownRoutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(resumeCountdownRoutine);
				resumeCountdownRoutine = null;
			}
			if (isResumeCountdownActive)
			{
				TeeOffCountdown.Hide();
			}
			isResumeCountdownActive = false;
		}

		private IEnumerator ResumeCountdownRoutine()
		{
			isResumeCountdownActive = true;
			pendingRemotePause = false;
			RestorePauseDances();
			RestorePauseBanner();
			float remainingTime = GetResumeCountdownDuration();
			TeeOffCountdown.Show();
			while (remainingTime > 0f && isPaused && CanApplyPauseState())
			{
				TeeOffCountdown.SetRemainingTime(remainingTime);
				remainingTime -= Time.unscaledDeltaTime;
				yield return null;
			}
			TeeOffCountdown.SetRemainingTime(0f);
			TeeOffCountdown.Hide();
			resumeCountdownRoutine = null;
			isResumeCountdownActive = false;
			ApplyPauseLocal(paused: false);
			if (NetworkServer.active)
			{
				PublishSteamLobbyPauseState("0");
			}
		}

		private static float GetResumeCountdownDuration()
		{
			float num = (((Object)(object)GameManager.MatchSettings != (Object)null) ? GameManager.MatchSettings.TeeOffCountdownDuration : 3f);
			return Mathf.Max(1f, num);
		}

		private static void ApplyRemotePause(bool paused)
		{
			ApplyRemotePauseState(paused ? "1" : "0");
		}

		private static void ApplyRemotePauseState(string state)
		{
			if (state == "2")
			{
				pendingRemotePause = false;
				BeginResumeCountdownLocal();
			}
			else if (state != "1")
			{
				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()
		{
			instance?.StopResumeCountdown();
			isPaused = false;
			isResumeCountdownActive = false;
			RestorePauseDances();
			RestoreRigidbodies();
			RestorePauseBanner();
			instance?.RefreshPauseButton();
		}

		private static bool ShouldBlockGameplay()
		{
			return isPaused;
		}

		private static bool CanApplyPauseState()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Invalid comparison between Unknown and I4
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			if (!NetworkServer.active && (!NetworkClient.active || NetworkClient.connection == null || !((NetworkConnection)NetworkClient.connection).isAuthenticated))
			{
				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<LocalizeStringEvent>(true);
				foreach (LocalizeStringEvent val in componentsInChildren)
				{
					if (((Behaviour)val).enabled)
					{
						((Behaviour)val).enabled = false;
						pauseBannerDisabledLocalizers.Add(val);
					}
				}
				TMP_Text[] componentsInChildren2 = ((Component)aheadOfBallMessage).GetComponentsInChildren<TMP_Text>(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<TMP_Text, string> 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 void DrawPauseOverlay()
		{
			//IL_004d: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			if (ShouldBlockGameplay() && !isResumeCountdownActive)
			{
				EnsurePauseOverlayStyles();
				float num = Mathf.Min(520f, (float)Screen.width - 48f);
				float num2 = 132f;
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, 42f, num, num2);
				GUI.Box(val, GUIContent.none, pauseOverlayBoxStyle);
				GUI.Label(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).y + 20f, ((Rect)(ref val)).width - 48f, 42f), "Game Paused", pauseOverlayTitleStyle);
				GUI.Label(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).y + 70f, ((Rect)(ref val)).width - 48f, 42f), NetworkServer.active ? "Host pause is active" : "Waiting for the host to resume", pauseOverlayDetailStyle);
			}
		}

		private static void EnsurePauseOverlayStyles()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0031: 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)
			//IL_0064: 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_0077: Expected O, but got Unknown
			//IL_0077: 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_008a: Expected O, but got Unknown
			//IL_008f: Expected O, but got Unknown
			//IL_0099: 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_00a5: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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_0105: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			if (pauseOverlayBoxStyle == null)
			{
				pauseOverlayTexture = new Texture2D(1, 1, (TextureFormat)4, false);
				pauseOverlayTexture.SetPixel(0, 0, new Color(0.05f, 0.1f, 0.12f, 0.88f));
				pauseOverlayTexture.Apply();
				GUIStyle val = new GUIStyle(GUI.skin.box);
				val.normal.background = pauseOverlayTexture;
				val.border = new RectOffset(12, 12, 12, 12);
				val.padding = new RectOffset(18, 18, 14, 14);
				pauseOverlayBoxStyle = val;
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontSize = Mathf.Clamp(Screen.height / 22, 28, 44),
					fontStyle = (FontStyle)1
				};
				val2.normal.textColor = Color.white;
				pauseOverlayTitleStyle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontSize = Mathf.Clamp(Screen.height / 42, 16, 24),
					fontStyle = (FontStyle)1
				};
				val3.normal.textColor = new Color(0.82f, 0.95f, 1f, 1f);
				pauseOverlayDetailStyle = val3;
			}
		}

		private static void DestroyPauseOverlayStyles()
		{
			if ((Object)(object)pauseOverlayTexture != (Object)null)
			{
				Object.Destroy((Object)(object)pauseOverlayTexture);
				pauseOverlayTexture = null;
			}
			pauseOverlayBoxStyle = null;
			pauseOverlayTitleStyle = null;
			pauseOverlayDetailStyle = null;
		}

		private static AheadOfBallMessage GetAheadOfBallMessage()
		{
			if (SingletonBehaviour<AheadOfBallMessage>.HasInstance)
			{
				return SingletonBehaviour<AheadOfBallMessage>.Instance;
			}
			return Object.FindFirstObjectByType<AheadOfBallMessage>((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<Rigidbody>((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 static void CancelPausedPlayerActions()
		{
			PlayerInput[] array = Object.FindObjectsByType<PlayerInput>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				ClearPausedInput(array[i]);
			}
			PlayerInfo[] array2 = Object.FindObjectsByType<PlayerInfo>((FindObjectsSortMode)0);
			for (int i = 0; i < array2.Length; i++)
			{
				ClearPausedPlayerState(array2[i]);
			}
			SwingPowerBarUi.CancelSwingCharge();
		}

		private static void ClearPausedInput(PlayerInput input)
		{
			if (!((Object)(object)input == (Object)null))
			{
				playerInputHoldingAimSwingField?.SetValue(input, false);
				playerInputHoldingChargeSwingField?.SetValue(input, false);
				object? obj = playerInputPlayerInfoField?.GetValue(input);
				ClearPausedPlayerState((PlayerInfo)((obj is PlayerInfo) ? obj : null));
			}
		}

		private static void ClearPausedPlayerState(PlayerInfo player)
		{
			if (!((Object)(object)player == (Object)null))
			{
				player.SetIsAimingSwing(false);
				player.SetIsAimingItem(false);
			}
		}

		private static void ApplyPauseDances()
		{
			PlayerInfo[] array = Object.FindObjectsByType<PlayerInfo>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				ApplyPauseDance(array[i]);
			}
		}

		private static void MaintainPauseDances()
		{
			PlayerInfo[] array = Object.FindObjectsByType<PlayerInfo>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				ApplyPauseDance(array[i]);
			}
		}

		private static void ApplyPauseDance(PlayerInfo player)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (CanPauseDance(player))
			{
				PlayerAnimatorIo animatorIo = player.AnimatorIo;
				if (!pauseDanceOriginalValues.ContainsKey(animatorIo))
				{
					pauseDanceOriginalValues[animatorIo] = GetCurrentVictoryDanceValue(animatorIo);
				}
				animatorIo.SetVictoryDance(player.Cosmetics.victoryDance);
			}
		}

		private static bool CanPauseDance(PlayerInfo player)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			if ((Object)(object)player == (Object)null || (Object)(object)player.AnimatorIo == (Object)null || (Object)(object)player.Cosmetics == (Object)null || (Object)(object)player.AsGolfer == (Object)null)
			{
				return false;
			}
			return (int)player.AsGolfer.MatchResolution == 0;
		}

		private static int GetCurrentVictoryDanceValue(PlayerAnimatorIo animatorIo)
		{
			object? obj = animatorField?.GetValue(animatorIo);
			Animator val = (Animator)((obj is Animator) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				return 0;
			}
			int num = ((victoryDanceHashField?.GetValue(null) is int num2 && num2 != 0) ? num2 : Animator.StringToHash("Victory dance"));
			return val.GetInteger(num);
		}

		private static void RestorePauseDances()
		{
			foreach (KeyValuePair<PlayerAnimatorIo, int> pauseDanceOriginalValue in pauseDanceOriginalValues)
			{
				if ((Object)(object)pauseDanceOriginalValue.Key != (Object)null)
				{
					pauseDanceOriginalValue.Key.SetVictoryDance((VictoryDance)pauseDanceOriginalValue.Value);
				}
			}
			pauseDanceOriginalValues.Clear();
		}

		private void AddPauseButton(PauseMenu pauseMenu)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: 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;
			}
			pauseButton = CreateHostPauseMenuButton(val, "HostPauseButton", ((Component)val).transform.GetSiblingIndex() + 1);
			pauseButton.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick = pauseButton.onClick;
			object obj = <>O.<0>__TogglePauseFromPauseMenu;
			if (obj == null)
			{
				UnityAction val2 = TogglePauseFromPauseMenu;
				<>O.<0>__TogglePauseFromPauseMenu = val2;
				obj = (object)val2;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			pauseButtonLabel = ((Component)pauseButton).GetComponentInChildren<TMP_Text>(true);
			backToLobbyButton = CreateHostPauseMenuButton(val, "HostPauseBackToLobbyButton", ((Component)val).transform.GetSiblingIndex() + 2);
			backToLobbyButton.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick2 = backToLobbyButton.onClick;
			object obj2 = <>O.<1>__ReturnToLobbyFromPauseMenu;
			if (obj2 == null)
			{
				UnityAction val3 = ReturnToLobbyFromPauseMenu;
				<>O.<1>__ReturnToLobbyFromPauseMenu = val3;
				obj2 = (object)val3;
			}
			((UnityEvent)onClick2).AddListener((UnityAction)obj2);
			backToLobbyButtonLabel = ((Component)backToLobbyButton).GetComponentInChildren<TMP_Text>(true);
			RefreshPauseButton();
			RefreshPauseMenuButtonList(pauseMenu);
			FitPauseMenuButtonStack(pauseMenu);
		}

		private static Button CreateHostPauseMenuButton(Button templateButton, string objectName, int siblingIndex)
		{
			GameObject val = Object.Instantiate<GameObject>(((Component)templateButton).gameObject, ((Component)templateButton).transform.parent);
			((Object)val).name = objectName;
			val.transform.SetSiblingIndex(siblingIndex);
			LocalizeStringEvent[] componentsInChildren = val.GetComponentsInChildren<LocalizeStringEvent>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Behaviour)componentsInChildren[i]).enabled = false;
			}
			return val.GetComponent<Button>();
		}

		private static Button FindPauseButtonTemplate(PauseMenu pauseMenu)
		{
			Button[] componentsInChildren = pauseMenu.menuButtonContainer.GetComponentsInChildren<Button>(true);
			Button[] array = componentsInChildren;
			foreach (Button val in array)
			{
				TMP_Text componentInChildren = ((Component)val).GetComponentInChildren<TMP_Text>(true);
				if ((Object)(object)componentInChildren != (Object)null && componentInChildren.text.Trim().Equals("Settings", StringComparison.OrdinalIgnoreCase))
				{
					return val;
				}
			}
			int num = Array.IndexOf(componentsInChildren, pauseMenu.exitGameButton);
			if (num > 0)
			{
				return componentsInChildren[num - 1];
			}
			if (!((Object)(object)pauseMenu.exitGameButton != (Object)null))
			{
				return pauseMenu.resumeButton;
			}
			return pauseMenu.exitGameButton;
		}

		private static void RefreshPauseMenuButtonList(PauseMenu pauseMenu)
		{
			Button[] componentsInChildren = pauseMenu.menuButtonContainer.GetComponentsInChildren<Button>(true);
			AccessTools.Field(typeof(PauseMenu), "allButtons")?.SetValue(pauseMenu, componentsInChildren);
			AccessTools.Method(typeof(PauseMenu), "UpdateButtonOffsets", (Type[])null, (Type[])null)?.Invoke(pauseMenu, null);
		}

		private static void FitPauseMenuButtonStack(PauseMenu pauseMenu)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = pauseMenu.menuButtonContainer.GetComponent<RectTransform>();
			if (!((Object)(object)component == (Object)null))
			{
				if (!pauseMenuStackAdjusted)
				{
					pauseMenuOriginalScale = ((Transform)component).localScale;
					pauseMenuOriginalAnchoredPosition = component.anchoredPosition;
					pauseMenuStackAdjusted = true;
				}
				((Transform)component).localScale = new Vector3(pauseMenuOriginalScale.x * 0.78f, pauseMenuOriginalScale.y * 0.78f, pauseMenuOriginalScale.z);
				component.anchoredPosition = pauseMenuOriginalAnchoredPosition + new Vector2(0f, 58f);
			}
		}

		private void RefreshPauseButton()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Invalid comparison between Unknown and I4
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Invalid comparison between Unknown and I4
			if (!((Object)(object)pauseButton == (Object)null))
			{
				bool active = NetworkServer.active;
				((Selectable)pauseButton).interactable = active;
				if ((Object)(object)pauseButtonLabel != (Object)null)
				{
					pauseButtonLabel.text = (active ? GetHostPauseButtonLabel() : "Host Pause Only");
				}
				if ((Object)(object)backToLobbyButton != (Object)null)
				{
					bool interactable = active && (int)CourseManager.MatchState >= 1 && (int)CourseManager.MatchState <= 6;
					((Selectable)backToLobbyButton).interactable = interactable;
				}
				if ((Object)(object)backToLobbyButtonLabel != (Object)null)
				{
					backToLobbyButtonLabel.text = (active ? "Back to Lobby" : "Host Only");
				}
			}
		}

		private static string GetHostPauseButtonLabel()
		{
			if (ShouldBlockGameplay())
			{
				return "Resume Game";
			}
			return "Pause Game";
		}

		private static bool AllowPausedInputAction(PlayerInput input)
		{
			if (!ShouldBlockGameplay())
			{
				return true;
			}
			ClearPausedInput(input);
			return false;
		}
	}
}