Decompiled source of Pause v0.0.3

Pause.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
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.Player;
using CG.Game.SpaceObjects.Controllers;
using CG.GameLoopStateMachine.GameStates;
using CG.Input;
using CG.Ship.Modules;
using CG.Space;
using Gameplay.Enhancements;
using Gameplay.Power;
using Gameplay.Ship;
using Gameplay.Utilities;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Character.Abilities;
using Opsive.UltimateCharacterController.Traits;
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("0.0.3.0")]
[assembly: AssemblyInformationalVersion("0.0.3+2ba816a61a02a0270ff73603bd1ffe85fb93238a")]
[assembly: AssemblyProduct("Pause")]
[assembly: AssemblyTitle("Allows the game to be paused during a Void Jump.")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.3.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("18107.Pause", "Pause", "0.0.3")]
	[BepInProcess("Void Crew.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class BepinPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "18107.Pause");
			Configs.Load(this);
			((Object)new GameObject("PausedGUI", new Type[1] { typeof(PausedGUI) })).hideFlags = (HideFlags)61;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin 18107.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);
		}
	}
	public class MyPluginInfo
	{
		public const string PLUGIN_GUID = "18107.Pause";

		public const string PLUGIN_NAME = "Pause";

		public const string USERS_PLUGIN_NAME = "Pause";

		public const string PLUGIN_VERSION = "0.0.3";

		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 = "18107";

		public const string PLUGIN_THUNDERSTORE_ID = "VoidCrewModdingTeam/Pause";
	}
	[HarmonyPatch(typeof(GSTallyScreen))]
	internal class GSTallyScreenPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("OnEnter")]
		private static void OnEnter()
		{
			PauseManager.Reset();
		}
	}
	[HarmonyPatch(typeof(VoidJumpTravellingStable))]
	internal class VoidJumpTravellingStablePatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("OnExit")]
		private static void OnExit()
		{
			PauseManager.Reset();
		}
	}
	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 = 1;

		private static readonly FieldInfo characterHealthField = AccessTools.Field(typeof(Player), "characterHealth");

		private static readonly FieldInfo OxygenDepositField = AccessTools.Field(typeof(LocalPlayer), "OxygenDeposit");

		private static readonly FieldInfo activationEndTimeField = AccessTools.Field(typeof(Enhancement), "_activationEndTime");

		private static readonly FieldInfo currentTemperatureField = AccessTools.Field(typeof(ProtectedPowerSystem), "currentTemperature");

		private static LocalPlayer player;

		private static float playerOxygen;

		private static bool wasInvulnerable;

		private static Vector3 position;

		private static int startTime;

		private static Dictionary<Enhancement, int> EngineTrims;

		private static ProtectedPowerSystem breakers;

		private static float breakerTemperature;

		private static bool _isPaused = false;

		internal static Player pausePlayer;

		private static bool stable = true;

		internal static bool IsPaused
		{
			get
			{
				return _isPaused;
			}
			private set
			{
				//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d4: Expected O, but got Unknown
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Expected O, but got Unknown
				//IL_0088: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
				if (value == _isPaused)
				{
					return;
				}
				_isPaused = value;
				if (value)
				{
					Events.Instance.LateUpdate += WhilePaused;
					player = LocalPlayer.Instance;
					CustomCharacterHealth val = (CustomCharacterHealth)characterHealthField.GetValue(player);
					wasInvulnerable = val.IsInvulnerable;
					val.IsInvulnerable = true;
					playerOxygen = ((Attribute)OxygenDepositField.GetValue(player)).Value;
					position = ((CharacterLocomotion)((Player)player).Locomotion).Transform.position;
					startTime = PhotonNetwork.ServerTimestamp;
					ClientGame current = ClientGame.Current;
					object engineTrims;
					if (current == null)
					{
						engineTrims = null;
					}
					else
					{
						AbstractPlayerControlledShip playerShip = current.PlayerShip;
						if (playerShip == null)
						{
							engineTrims = null;
						}
						else
						{
							Helm module = playerShip.GetModule<Helm>();
							if (module == null)
							{
								engineTrims = null;
							}
							else
							{
								ShipEngine engine = module.Engine;
								engineTrims = ((engine != null) ? ((Component)engine).GetComponentsInChildren<Enhancement>().ToDictionary((Enhancement trim) => trim, (Enhancement trim) => (int)activationEndTimeField.GetValue(trim) - startTime) : null);
							}
						}
					}
					EngineTrims = (Dictionary<Enhancement, int>)engineTrims;
					ClientGame current2 = ClientGame.Current;
					object obj;
					if (current2 == null)
					{
						obj = null;
					}
					else
					{
						AbstractPlayerControlledShip playerShip2 = current2.PlayerShip;
						obj = ((playerShip2 != null) ? ((Component)playerShip2).GetComponentInChildren<ProtectedPowerSystem>() : null);
					}
					breakers = (ProtectedPowerSystem)obj;
					float num = (float)currentTemperatureField.GetValue(breakers);
					breakerTemperature = Mathf.Min(num - ((ModifiablePrimitive<float, FloatModifier>)(object)breakers.BreakerTemperatureShiftSpeed).Value, num);
				}
				else
				{
					Events.Instance.LateUpdate -= WhilePaused;
					player = LocalPlayer.Instance;
					CustomCharacterHealth val2 = (CustomCharacterHealth)characterHealthField.GetValue(player);
					val2.IsInvulnerable = wasInvulnerable;
				}
			}
		}

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


		internal static void TryTogglePause(Player pauser = null)
		{
			if (!PhotonNetwork.IsMasterClient)
			{
				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)
			{
				IsPaused = false;
			}
			else
			{
				if (!(val2 is VoidJumpTravellingStable) && !(val2 is VoidJumpTravellingUnstable))
				{
					return;
				}
				pausePlayer = pauser ?? PhotonNetwork.LocalPlayer;
				if (IsPaused)
				{
					IsPaused = false;
					if (!stable)
					{
						val.ChangeActiveState<VoidJumpTravellingUnstable>();
						stable = true;
					}
				}
				else
				{
					IsPaused = true;
					if (val2 is VoidJumpTravellingUnstable)
					{
						stable = false;
						val.ChangeActiveState<VoidJumpTravellingStable>();
					}
				}
				SendPause(IsPaused, pausePlayer);
			}
		}

		private static void WhilePaused(object o, EventArgs e)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			Attribute val = (Attribute)OxygenDepositField.GetValue(player);
			if (val.Value < playerOxygen)
			{
				val.Value = playerOxygen;
			}
			if (((IEnumerable<Ability>)((UltimateCharacterLocomotion)((Player)player).Locomotion).Abilities).FirstOrDefault((Func<Ability, bool>)((Ability ability) => ability is MoveThroughPoints)).IsActive)
			{
				position = ((CharacterLocomotion)((Player)player).Locomotion).Transform.position;
			}
			if (((CharacterLocomotion)((Player)player).Locomotion).Transform.position != position)
			{
				((CharacterLocomotion)((Player)player).Locomotion).Transform.position = position;
			}
			int serverTimestamp = PhotonNetwork.ServerTimestamp;
			foreach (KeyValuePair<Enhancement, int> engineTrim in EngineTrims)
			{
				Enhancement key = engineTrim.Key;
				int value = engineTrim.Value;
				activationEndTimeField.SetValue(key, serverTimestamp + value);
			}
			currentTemperatureField.SetValue(breakers, breakerTemperature);
		}

		internal static void Reset()
		{
			IsPaused = false;
		}

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

		internal static void RequestPause(bool pause)
		{
			if (!PhotonNetwork.IsMasterClient)
			{
				Send(new object[3]
				{
					1,
					MessageType.Pause,
					pause
				}, PhotonNetwork.MasterClient);
			}
		}

		internal static void SendPause(bool pause, Player pauser, params Player[] players)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				Send(new object[4]
				{
					1,
					MessageType.Pause,
					pause,
					pauser.ActorNumber
				}, players);
			}
		}

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

		private static void Send(object[] arguments, params Player[] players)
		{
			if (players.Length != 0)
			{
				ModMessage.Send("18107.Pause", ModMessage.GetIdentifier(typeof(PauseManager)), players, arguments, true);
			}
			else
			{
				ModMessage.Send("18107.Pause", ModMessage.GetIdentifier(typeof(PauseManager)), (ReceiverGroup)0, arguments, true);
			}
		}
	}
	public class VoidManagerPlugin : VoidPlugin
	{
		public override MultiplayerType MPType => (MultiplayerType)30;

		public override string Author => "18107";

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

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

		public VoidManagerPlugin()
		{
			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();
						}
					}
				}
			};
		}
	}
}