Decompiled source of Pause v1.0.0

Pause.dll

Decompiled a week ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CG;
using CG.Game;
using CG.Game.SpaceObjects.Controllers;
using CG.Input;
using CG.Space;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using VoidManager;
using VoidManager.CustomGUI;
using VoidManager.MPModChecks;
using VoidManager.ModMessages;
using VoidManager.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Pause")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ac1a08ccd0b69114cebdadf2c012548719f04284")]
[assembly: AssemblyProduct("Pause")]
[assembly: AssemblyTitle("Allows the game to be paused during a Void Jump.")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.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 Pause
{
	[BepInPlugin("VoidCrewModdingTeam.Pause", "Pause", "1.0.0")]
	[BepInProcess("Void Crew.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class BepinPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Configs.Load(this);
			((Object)new GameObject("PausedGUI", new Type[1] { typeof(PausedGUI) })).hideFlags = (HideFlags)61;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin VoidCrewModdingTeam.Pause is loaded!");
		}
	}
	internal class Configs
	{
		internal static ConfigEntry<KeyCode> pauseKeyConfig;

		internal static ConfigEntry<bool> playersCanPauseConfig;

		internal static void Load(BepinPlugin plugin)
		{
			pauseKeyConfig = ((BaseUnityPlugin)plugin).Config.Bind<KeyCode>("Pause", "PauseKey", (KeyCode)278, (ConfigDescription)null);
			playersCanPauseConfig = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Pause", "PlayersCanPause", false, (ConfigDescription)null);
		}
	}
	internal class GUI : ModSettingsMenu
	{
		public override string Name()
		{
			return "Pause";
		}

		public override void Draw()
		{
			ClientGame current = ClientGame.Current;
			object obj;
			if (current == null)
			{
				obj = null;
			}
			else
			{
				AbstractPlayerControlledShip playerShip = current.PlayerShip;
				if (playerShip == null)
				{
					obj = null;
				}
				else
				{
					Transform transform = ((Component)playerShip).transform;
					obj = ((transform != null) ? ((Component)transform).GetComponent<VoidJumpSystem>() : null);
				}
			}
			VoidJumpSystem val = (VoidJumpSystem)obj;
			VoidJumpState val2 = ((val != null) ? val.ActiveState : null);
			GUILayout.Label("", Array.Empty<GUILayoutOption>());
			if (PhotonNetwork.IsMasterClient || PauseManager.CanPause)
			{
				if (val2 is VoidJumpTravellingStable || val2 is VoidJumpTravellingUnstable)
				{
					if (GUILayout.Button(PauseManager.IsPaused ? "Resume" : "Pause", Array.Empty<GUILayoutOption>()))
					{
						PauseManager.TryTogglePause();
					}
				}
				else
				{
					GUILayout.Button("Pause only available in Void Jump", Array.Empty<GUILayoutOption>());
				}
			}
			else
			{
				GUILayout.Button((PauseManager.IsPaused ? "Resume" : "Pause") + " not permitted by host", Array.Empty<GUILayoutOption>());
			}
			GUILayout.Label("", Array.Empty<GUILayoutOption>());
			if (GUITools.DrawCheckbox("Allow other players to pause/resume", ref Configs.playersCanPauseConfig))
			{
				PauseManager.SendCanPause();
			}
			GUITools.DrawChangeKeybindButton("Pause keybind", ref Configs.pauseKeyConfig);
		}
	}
	[HarmonyPatch("UnityEngine.UIElements.Panel, UnityEngine.UIElementsModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", "DefaultTimeSinceStartupMs")]
	internal class HudTimersPatch
	{
		private static bool Prefix(ref long __result)
		{
			__result = (long)(Time.time * 1000f);
			return false;
		}
	}
	public class MyPluginInfo
	{
		public const string PLUGIN_GUID = "VoidCrewModdingTeam.Pause";

		public const string PLUGIN_NAME = "Pause";

		public const string USERS_PLUGIN_NAME = "Pause";

		public const string PLUGIN_VERSION = "1.0.0";

		public const string PLUGIN_DESCRIPTION = "Allows the game to be paused during a Void Jump.";

		public const string PLUGIN_ORIGINAL_AUTHOR = "18107";

		public const string PLUGIN_AUTHORS = "Dragon, 18107";

		public const string PLUGIN_THUNDERSTORE_ID = "VoidCrewModdingTeam/Pause";
	}
	internal class PausedGUI : MonoBehaviour, IShowCursorSource, IInputActionMapRequest
	{
		private bool guiActive = false;

		private Rect WindowPos;

		private PausedGUI()
		{
		}

		private void Update()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (PauseManager.IsPaused != guiActive)
			{
				InputActionMapRequests.RemoveRequest((IInputActionMapRequest)(object)this);
				guiActive = PauseManager.IsPaused;
				if (guiActive)
				{
					WindowPos = new Rect((float)Screen.width / 4f, (float)Screen.height / 4f, (float)Screen.width / 2f, (float)Screen.height / 2f);
				}
				CursorUtility.ShowCursor((IShowCursorSource)(object)this, guiActive);
			}
		}

		private void OnGUI()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (guiActive)
			{
				InputActionMapRequests.AddOrChangeRequest((IInputActionMapRequest)(object)this, (InputStateRequestType)2);
				GUI.Window(618107, WindowPos, new WindowFunction(WindowFunction), "Game Paused");
			}
		}

		private void WindowFunction(int WindowID)
		{
			GUILayout.FlexibleSpace();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			if (PauseManager.pausePlayer != null)
			{
				GUILayout.Label("Game paused by " + PauseManager.pausePlayer.NickName, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label("Game paused", Array.Empty<GUILayoutOption>());
			}
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.Label("", Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			if (PhotonNetwork.IsMasterClient || PauseManager.CanPause)
			{
				if (GUILayout.Button("     Resume     ", Array.Empty<GUILayoutOption>()))
				{
					PauseManager.TryTogglePause();
				}
			}
			else
			{
				GUILayout.Button((PauseManager.IsPaused ? "Resume" : "Pause") + " not permitted by host", Array.Empty<GUILayoutOption>());
			}
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.FlexibleSpace();
		}
	}
	internal class PauseManager : ModMessage
	{
		private enum MessageType
		{
			Pause,
			CanPause
		}

		private const int version = 2;

		private static bool _isPaused = false;

		internal static Player pausePlayer;

		private static bool stable = true;

		internal static bool IsPaused
		{
			get
			{
				return _isPaused;
			}
			private set
			{
				if (value != _isPaused)
				{
					_isPaused = value;
					if (value)
					{
						PhotonNetwork.MinimalTimeScaleToDispatchInFixedUpdate = 0f;
						Time.timeScale = 0f;
					}
					else
					{
						Time.timeScale = 1f;
						PhotonNetwork.MinimalTimeScaleToDispatchInFixedUpdate = -1f;
					}
				}
			}
		}

		internal static bool CanPause { get; private set; } = false;


		internal static void TryTogglePause(Player pauser = null)
		{
			if (!PhotonNetwork.IsMasterClient)
			{
				BepinPlugin.Log.LogInfo((object)"TryToggle non-host triggered.");
				RequestPause(!IsPaused);
				return;
			}
			ClientGame current = ClientGame.Current;
			object obj;
			if (current == null)
			{
				obj = null;
			}
			else
			{
				AbstractPlayerControlledShip playerShip = current.PlayerShip;
				if (playerShip == null)
				{
					obj = null;
				}
				else
				{
					Transform transform = ((Component)playerShip).transform;
					obj = ((transform != null) ? ((Component)transform).GetComponent<VoidJumpSystem>() : null);
				}
			}
			VoidJumpSystem val = (VoidJumpSystem)obj;
			VoidJumpState val2 = ((val != null) ? val.ActiveState : null);
			if (val2 == null || (!(val2 is VoidJumpTravellingStable) && !(val2 is VoidJumpTravellingUnstable)))
			{
				IsPaused = false;
				return;
			}
			IsPaused = !IsPaused;
			BepinPlugin.Log.LogInfo((object)"Toggled Pause from handler");
			ServerTimestampPatch.UpdateTiming(IsPaused);
			pausePlayer = pauser ?? PhotonNetwork.LocalPlayer;
			SendPause(IsPaused, pausePlayer);
		}

		internal static void Reset()
		{
			IsPaused = false;
			ServerTimestampPatch.PauseTotal = 0;
		}

		public override void Handle(object[] arguments, Player sender)
		{
			if (arguments.Length < 3)
			{
				return;
			}
			if ((int)arguments[0] != 2)
			{
				BepinPlugin.Log.LogInfo((object)$"Received version {(int)arguments[0]}, expected {2}");
			}
			else if (PhotonNetwork.IsMasterClient)
			{
				BepinPlugin.Log.LogInfo((object)$"Recieved Pause Request ({(bool)arguments[2]}) message from {sender.NickName}");
				if ((MessageType)arguments[1] == MessageType.Pause && Configs.playersCanPauseConfig.Value && (bool)arguments[2] != IsPaused)
				{
					pausePlayer = sender;
					TryTogglePause(pausePlayer);
				}
			}
			else
			{
				if (!sender.IsMasterClient)
				{
					return;
				}
				switch ((MessageType)arguments[1])
				{
				case MessageType.Pause:
					BepinPlugin.Log.LogInfo((object)$"Recieved Pause ({(bool)arguments[2]}) message from {sender.NickName}");
					IsPaused = (bool)arguments[2];
					if (arguments.Length > 3)
					{
						pausePlayer = PhotonNetwork.CurrentRoom.GetPlayer((int)arguments[3], false);
						ServerTimestampPatch.PauseTotal = (int)arguments[4];
						ServerTimestampPatch.UpdateTiming(paused: true);
					}
					break;
				case MessageType.CanPause:
					BepinPlugin.Log.LogInfo((object)("Recieved CanPause message from " + sender.NickName));
					CanPause = (bool)arguments[2];
					break;
				}
			}
		}

		internal static void RequestPause(bool pause)
		{
			if (!PhotonNetwork.IsMasterClient)
			{
				Send(new object[3]
				{
					2,
					MessageType.Pause,
					pause
				}, PhotonNetwork.MasterClient);
				BepinPlugin.Log.LogInfo((object)"RequestPause sent.");
			}
		}

		internal static void SendPause(bool pause, Player pauser, params Player[] players)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				Send(new object[5]
				{
					2,
					MessageType.Pause,
					pause,
					pauser.ActorNumber,
					ServerTimestampPatch.GetPauseTotalForClient()
				}, players);
				BepinPlugin.Log.LogInfo((object)"SendPause sent.");
			}
		}

		internal static void SendCanPause(params Player[] players)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				Send(new object[3]
				{
					2,
					MessageType.CanPause,
					Configs.playersCanPauseConfig.Value
				}, players);
			}
		}

		private static void Send(object[] arguments, params Player[] players)
		{
			if (players.Length != 0)
			{
				ModMessage.Send("VoidCrewModdingTeam.Pause", ModMessage.GetIdentifier(typeof(PauseManager)), players, arguments, true);
			}
			else
			{
				ModMessage.Send("VoidCrewModdingTeam.Pause", ModMessage.GetIdentifier(typeof(PauseManager)), (ReceiverGroup)0, arguments, true);
			}
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal class ServerTimestampPatch
	{
		internal static int cachedServerTime;

		internal static int PauseTotal;

		private static FieldInfo StartupStopwatchFI = AccessTools.Field(typeof(PhotonNetwork), "StartupStopwatch");

		internal static int GetPauseTotalForClient()
		{
			if (PauseManager.IsPaused)
			{
				return PauseTotal + UnmodifiedServerTimestamp() - cachedServerTime;
			}
			return PauseTotal;
		}

		public static int UnmodifiedServerTimestamp()
		{
			if (!PhotonNetwork.OfflineMode)
			{
				return ((PhotonPeer)PhotonNetwork.NetworkingClient.LoadBalancingPeer).ServerTimeInMilliSeconds;
			}
			if (StartupStopwatchFI.GetValue(null) != null && ((Stopwatch)StartupStopwatchFI.GetValue(null)).IsRunning)
			{
				return (int)((Stopwatch)StartupStopwatchFI.GetValue(null)).ElapsedMilliseconds;
			}
			return Environment.TickCount;
		}

		internal static void UpdateTiming(bool paused)
		{
			if (paused)
			{
				cachedServerTime = UnmodifiedServerTimestamp();
			}
			else
			{
				PauseTotal += UnmodifiedServerTimestamp() - cachedServerTime;
			}
		}

		private static void Postfix(ref int __result)
		{
			if (PauseManager.IsPaused)
			{
				__result = cachedServerTime - PauseTotal;
			}
			else
			{
				__result -= PauseTotal;
			}
		}
	}
	public class VoidManagerPlugin : VoidPlugin
	{
		public override MultiplayerType MPType => (MultiplayerType)30;

		public override string Author => "Dragon, 18107";

		public override string Description => "Allows the game to be paused during a Void Jump.";

		public override string ThunderstoreID => "VoidCrewModdingTeam/Pause";

		public VoidManagerPlugin()
		{
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "VoidCrewModdingTeam.Pause");
			Events.Instance.PlayerEnteredRoom += delegate(object _, PlayerEventArgs playerEventArgs)
			{
				PauseManager.SendCanPause(playerEventArgs.player);
				PauseManager.SendPause(PauseManager.IsPaused, PauseManager.pausePlayer ?? PhotonNetwork.LocalPlayer, playerEventArgs.player);
			};
			Events.Instance.MasterClientSwitched += delegate
			{
				PauseManager.SendCanPause();
				PauseManager.SendPause(PauseManager.IsPaused, PauseManager.pausePlayer ?? PhotonNetwork.LocalPlayer);
			};
			Events.Instance.LeftRoom += delegate
			{
				PauseManager.Reset();
			};
			Events.Instance.LateUpdate += delegate
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				if ((int)Configs.pauseKeyConfig.Value != 0 && UnityInput.Current.GetKeyDown(Configs.pauseKeyConfig.Value) && (!ServiceBase<InputService>.Instance.CursorVisibilityControl.IsCursorShown || PauseManager.IsPaused))
				{
					if (!PhotonNetwork.IsMasterClient && !PauseManager.CanPause)
					{
						Messaging.Notification("Not permitted by host", 8000L, false);
					}
					else
					{
						ClientGame current = ClientGame.Current;
						object obj;
						if (current == null)
						{
							obj = null;
						}
						else
						{
							AbstractPlayerControlledShip playerShip = current.PlayerShip;
							if (playerShip == null)
							{
								obj = null;
							}
							else
							{
								Transform transform = ((Component)playerShip).transform;
								obj = ((transform != null) ? ((Component)transform).GetComponent<VoidJumpSystem>() : null);
							}
						}
						VoidJumpSystem val = (VoidJumpSystem)obj;
						VoidJumpState val2 = ((val != null) ? val.ActiveState : null);
						if (val2 == null || (!(val2 is VoidJumpTravellingStable) && !(val2 is VoidJumpTravellingUnstable)))
						{
							Messaging.Notification("Not in void jump", 8000L, false);
						}
						else
						{
							PauseManager.TryTogglePause();
						}
					}
				}
			};
		}
	}
}