Decompiled source of Pause v0.0.2

Pause.dll

Decompiled 2 months 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.PowerSystem;
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: AssemblyDescription("Template")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Pause")]
[assembly: AssemblyTitle("Pause")]
[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
{
	internal static class MyPluginInfo
	{
		internal const string PLUGIN_GUID = "id107.pause";

		internal const string PLUGIN_NAME = "Pause";

		internal const string PLUGIN_VERSION = "0.0.2";
	}
	[BepInPlugin("id107.pause", "Pause", "0.0.2")]
	[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(), "id107.pause");
			Configs.Load(this);
			((Object)new GameObject("PausedGUI", new Type[1] { typeof(PausedGUI) })).hideFlags = (HideFlags)61;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin id107.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(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(718107, 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_01c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d0: Expected O, but got Unknown
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Expected O, but got Unknown
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				if (value != _isPaused)
				{
					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;
					}
				}
				_isPaused = value;
			}
		}

		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("id107.pause", ModMessage.GetIdentifier(typeof(PauseManager)), players, arguments, true);
			}
			else
			{
				ModMessage.Send("id107.pause", ModMessage.GetIdentifier(typeof(PauseManager)), (ReceiverGroup)0, arguments, true);
			}
		}
	}
	public class VoidManagerPlugin : VoidPlugin
	{
		public override MultiplayerType MPType => (MultiplayerType)10;

		public override string Author => "18107";

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

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