Decompiled source of RetryButton v1.0.1

plugins/RespawnButton/RespawnButton.dll

Decompiled 4 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HG.Reflection;
using IL.RoR2;
using Microsoft.CodeAnalysis;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using On.RoR2.UI;
using ProperSave;
using R2API.Utils;
using RespawnButton.Patches;
using RoR2;
using RoR2.UI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: OptIn]
[assembly: NetworkCompatibility(/*Could not decode attribute arguments.*/)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("RespawnButton")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RespawnButton")]
[assembly: AssemblyTitle("RespawnButton")]
[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 RespawnButton
{
	internal static class LanguageFolderHandler
	{
		public static void Register(string searchFolder, string langFolderName = "lang")
		{
			string langFolderPath = Path.Combine(searchFolder, langFolderName);
			if (Directory.Exists(langFolderPath))
			{
				Language.collectLanguageRootFolders += delegate(List<string> folders)
				{
					folders.Add(langFolderPath);
				};
			}
		}
	}
	internal static class Log
	{
		internal static ManualLogSource _logSource;

		internal static void Init(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		private static string getLogPrefix(string callerPath, string callerMemberName, int callerLineNumber)
		{
			int num = callerPath.LastIndexOf("RespawnButton\\");
			if (num >= 0)
			{
				callerPath = callerPath.Substring(num + "RespawnButton\\".Length);
			}
			return $"{callerPath}:{callerLineNumber} ({callerMemberName}) ";
		}

		internal static void Error(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1)
		{
			_logSource.LogError((object)(getLogPrefix(callerPath, callerMemberName, callerLineNumber) + data));
		}

		internal static void Error_NoCallerPrefix(object data)
		{
			_logSource.LogError(data);
		}

		internal static void Fatal(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1)
		{
			_logSource.LogFatal((object)(getLogPrefix(callerPath, callerMemberName, callerLineNumber) + data));
		}

		internal static void Fatal_NoCallerPrefix(object data)
		{
			_logSource.LogFatal(data);
		}

		internal static void Info(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1)
		{
			_logSource.LogInfo((object)(getLogPrefix(callerPath, callerMemberName, callerLineNumber) + data));
		}

		internal static void Info_NoCallerPrefix(object data)
		{
			_logSource.LogInfo(data);
		}

		internal static void Message(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1)
		{
			_logSource.LogMessage((object)(getLogPrefix(callerPath, callerMemberName, callerLineNumber) + data));
		}

		internal static void Message_NoCallerPrefix(object data)
		{
			_logSource.LogMessage(data);
		}

		internal static void Warning(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1)
		{
			_logSource.LogWarning((object)(getLogPrefix(callerPath, callerMemberName, callerLineNumber) + data));
		}

		internal static void Warning_NoCallerPrefix(object data)
		{
			_logSource.LogWarning(data);
		}
	}
	[BepInPlugin("Gorakh.RespawnButton", "RespawnButton", "1.0.1")]
	public class Main : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_Awake <0>__GameEndReportPanelController_Awake;

			public static hook_SetDisplayData <1>__GameEndReportPanelController_SetDisplayData;
		}

		public const string PluginGUID = "Gorakh.RespawnButton";

		public const string PluginAuthor = "Gorakh";

		public const string PluginName = "RespawnButton";

		public const string PluginVersion = "1.0.1";

		internal static Main Instance { get; private set; }

		private void Awake()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			Stopwatch stopwatch = Stopwatch.StartNew();
			Log.Init(((BaseUnityPlugin)this).Logger);
			Instance = SingletonHelper.Assign<Main>(Instance, this);
			LanguageFolderHandler.Register(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location));
			object obj = <>O.<0>__GameEndReportPanelController_Awake;
			if (obj == null)
			{
				hook_Awake val = GameEndReportPanelController_Awake;
				<>O.<0>__GameEndReportPanelController_Awake = val;
				obj = (object)val;
			}
			GameEndReportPanelController.Awake += (hook_Awake)obj;
			object obj2 = <>O.<1>__GameEndReportPanelController_SetDisplayData;
			if (obj2 == null)
			{
				hook_SetDisplayData val2 = GameEndReportPanelController_SetDisplayData;
				<>O.<1>__GameEndReportPanelController_SetDisplayData = val2;
				obj2 = (object)val2;
			}
			GameEndReportPanelController.SetDisplayData += (hook_SetDisplayData)obj2;
			stopwatch.Stop();
			Log.Info_NoCallerPrefix($"Initialized in {stopwatch.Elapsed.TotalSeconds:F2} seconds");
		}

		private static void GameEndReportPanelController_Awake(orig_Awake orig, GameEndReportPanelController self)
		{
			orig.Invoke(self);
			((Component)self).gameObject.AddComponent<RespawnButtonController>();
		}

		private static void GameEndReportPanelController_SetDisplayData(orig_SetDisplayData orig, GameEndReportPanelController self, DisplayData newDisplayData)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self, newDisplayData);
			RespawnButtonController respawnButtonController = default(RespawnButtonController);
			if (((Component)self).TryGetComponent<RespawnButtonController>(ref respawnButtonController))
			{
				respawnButtonController.OnSetDisplayData(newDisplayData);
			}
		}

		private void OnDestroy()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0040: 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_004b: Expected O, but got Unknown
			Instance = SingletonHelper.Unassign<Main>(Instance, this);
			object obj = <>O.<0>__GameEndReportPanelController_Awake;
			if (obj == null)
			{
				hook_Awake val = GameEndReportPanelController_Awake;
				<>O.<0>__GameEndReportPanelController_Awake = val;
				obj = (object)val;
			}
			GameEndReportPanelController.Awake -= (hook_Awake)obj;
			object obj2 = <>O.<1>__GameEndReportPanelController_SetDisplayData;
			if (obj2 == null)
			{
				hook_SetDisplayData val2 = GameEndReportPanelController_SetDisplayData;
				<>O.<1>__GameEndReportPanelController_SetDisplayData = val2;
				obj2 = (object)val2;
			}
			GameEndReportPanelController.SetDisplayData -= (hook_SetDisplayData)obj2;
		}
	}
	public class RespawnButtonController : MonoBehaviour
	{
		private Transform _respawnButtonInstance;

		private GameEndReportPanelController _gameEndPanelController;

		public bool IsVisible
		{
			get
			{
				if (Object.op_Implicit((Object)(object)_respawnButtonInstance))
				{
					return ((Component)_respawnButtonInstance).gameObject.activeSelf;
				}
				return false;
			}
			set
			{
				//IL_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_008c: Expected O, but got Unknown
				if (IsVisible == value)
				{
					return;
				}
				if (!Object.op_Implicit((Object)(object)_respawnButtonInstance))
				{
					if (!value)
					{
						return;
					}
					MPButton continueButton = _gameEndPanelController.continueButton;
					if (Object.op_Implicit((Object)(object)continueButton))
					{
						GameObject val = Object.Instantiate<GameObject>(((Component)continueButton).gameObject, ((Component)continueButton).transform.parent);
						val.transform.SetAsLastSibling();
						((Object)val).name = "RespawnButton";
						HGButton component = val.GetComponent<HGButton>();
						((UnityEventBase)((Button)component).onClick).RemoveAllListeners();
						((UnityEvent)((Button)component).onClick).AddListener(new UnityAction(onRespawnClicked));
						((Selectable)component).interactable = shouldBeInteractable();
						LanguageTextMeshController componentInChildren = val.GetComponentInChildren<LanguageTextMeshController>();
						if (Object.op_Implicit((Object)(object)componentInChildren))
						{
							componentInChildren.token = "GAME_REPORT_SCREEN_RESPAWN_BUTTON_LABEL";
						}
						Transform val2 = val.transform.Find("GenericGlyph");
						if (Object.op_Implicit((Object)(object)val2))
						{
							((Component)val2).gameObject.SetActive(false);
						}
						_respawnButtonInstance = val.transform;
					}
				}
				else
				{
					((Component)_respawnButtonInstance).gameObject.SetActive(value);
				}
			}
		}

		private static bool shouldShowOnReportScreen(RunReport runReport)
		{
			if (!NetworkServer.dontListen)
			{
				Run instance = Run.instance;
				if (instance is EclipseRun || instance is WeeklyRun)
				{
					return false;
				}
			}
			if (runReport == null)
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)runReport.gameEnding) || runReport.gameEnding.isWin)
			{
				return false;
			}
			return true;
		}

		private static bool shouldBeInteractable()
		{
			return Loading.CurrentSave != null;
		}

		private void Awake()
		{
			_gameEndPanelController = ((Component)this).GetComponent<GameEndReportPanelController>();
		}

		public void OnSetDisplayData(DisplayData newDisplayData)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			IsVisible = NetworkServer.active && shouldShowOnReportScreen(newDisplayData.runReport);
		}

		private void onRespawnClicked()
		{
			if (!Object.op_Implicit((Object)(object)Run.instance))
			{
				return;
			}
			SceneDef currentRunScene = SceneCatalog.mostRecentSceneDef;
			ProperSave_SaveFileDeletionHook.SuppressSaveFileDeletion = true;
			OverridePostRunDestinationPatch.OverridePostRunDestinationDelegate oldPostRunDestinationOverride = OverridePostRunDestinationPatch.PostRunDestinationOverride;
			OverridePostRunDestinationPatch.PostRunDestinationOverride = delegate
			{
				if (NetworkServer.active)
				{
					NetworkManager.singleton.ServerChangeScene("lobby");
				}
			};
			try
			{
				NetworkSession.instance.EndRun();
			}
			finally
			{
				((MonoBehaviour)RoR2Application.instance).StartCoroutine(waitThenDisableSaveSuppression());
			}
			((MonoBehaviour)RoR2Application.instance).StartCoroutine(waitForLobbyLoadThenLoadSave());
			IEnumerator waitForLobbyLoadThenLoadSave()
			{
				SceneDef characterSelectScene = SceneCatalog.FindSceneDef("lobby");
				while ((Object)(object)SceneCatalog.mostRecentSceneDef != (Object)(object)characterSelectScene)
				{
					if ((Object)(object)SceneCatalog.mostRecentSceneDef != (Object)(object)currentRunScene)
					{
						Log.Info("Unexpected exit scene, run exited to " + SceneCatalog.mostRecentSceneDef.cachedName + ", expected " + characterSelectScene.cachedName + ". Aborting restart.", "X:\\Git\\RoR2\\RespawnButton\\RespawnButton\\RespawnButtonController.cs", "onRespawnClicked", 159);
						yield break;
					}
					yield return 0;
				}
				yield return (object)new WaitUntil((Func<bool>)NetworkUser.AllParticipatingNetworkUsersReady);
				yield return (object)new WaitForEndOfFrame();
				yield return Loading.LoadLobby();
			}
			IEnumerator waitThenDisableSaveSuppression()
			{
				yield return (object)new WaitForEndOfFrame();
				ProperSave_SaveFileDeletionHook.SuppressSaveFileDeletion = false;
				OverridePostRunDestinationPatch.PostRunDestinationOverride = oldPostRunDestinationOverride;
			}
		}
	}
}
namespace RespawnButton.Patches
{
	internal static class OverridePostRunDestinationPatch
	{
		public delegate void OverridePostRunDestinationDelegate(Run run);

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<Instruction, bool> <>9__2_1;

			public static Func<Run, bool> <>9__2_2;

			public static Manipulator <>9__2_0;

			internal void <Init>b__2_0(ILContext il)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Expected O, but got Unknown
				//IL_004e: 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)
				ILCursor val = new ILCursor(il);
				if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
				{
					(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<Run>(x, "HandlePostRunDestination")
				}))
				{
					ILLabel val2 = val.MarkLabel();
					val.Index -= 2;
					val.Emit(OpCodes.Ldarg_0);
					val.EmitDelegate<Func<Run, bool>>((Func<Run, bool>)delegate(Run run)
					{
						if (PostRunDestinationOverride == null)
						{
							return true;
						}
						PostRunDestinationOverride(run);
						return false;
					});
					val.Emit(OpCodes.Brfalse, (object)val2);
				}
				else
				{
					Log.Error("Failed to find patch location", "X:\\Git\\RoR2\\RespawnButton\\RespawnButton\\Patches\\OverridePostRunDestinationPatch.cs", "Init", 42);
				}
			}

			internal bool <Init>b__2_1(Instruction x)
			{
				return ILPatternMatchingExt.MatchCallOrCallvirt<Run>(x, "HandlePostRunDestination");
			}

			internal bool <Init>b__2_2(Run run)
			{
				if (PostRunDestinationOverride == null)
				{
					return true;
				}
				PostRunDestinationOverride(run);
				return false;
			}
		}

		public static OverridePostRunDestinationDelegate PostRunDestinationOverride;

		[SystemInitializer(new Type[] { })]
		private static void Init()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			object obj = <>c.<>9__2_0;
			if (obj == null)
			{
				Manipulator val = delegate(ILContext il)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0007: Expected O, but got Unknown
					//IL_004e: 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)
					ILCursor val2 = new ILCursor(il);
					if (val2.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
					{
						(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<Run>(x, "HandlePostRunDestination")
					}))
					{
						ILLabel val3 = val2.MarkLabel();
						val2.Index -= 2;
						val2.Emit(OpCodes.Ldarg_0);
						val2.EmitDelegate<Func<Run, bool>>((Func<Run, bool>)delegate(Run run)
						{
							if (PostRunDestinationOverride == null)
							{
								return true;
							}
							PostRunDestinationOverride(run);
							return false;
						});
						val2.Emit(OpCodes.Brfalse, (object)val3);
					}
					else
					{
						Log.Error("Failed to find patch location", "X:\\Git\\RoR2\\RespawnButton\\RespawnButton\\Patches\\OverridePostRunDestinationPatch.cs", "Init", 42);
					}
				};
				<>c.<>9__2_0 = val;
				obj = (object)val;
			}
			Run.OnDestroy += (Manipulator)obj;
		}
	}
	internal static class ProperSave_SaveFileDeletionHook
	{
		private delegate void orig_Saving_RunOnServerGameOver(Run run, GameEndingDef ending);

		private static orig_Saving_RunOnServerGameOver _origRunOnServerGameOver;

		public static bool SuppressSaveFileDeletion;

		private static bool _deleteSaveFileOnRunEnd;

		private static Run _lastRunInstance;

		private static GameEndingDef _lastGameEndingDef;

		[SystemInitializer(new Type[] { })]
		private static void Init()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			_origRunOnServerGameOver = new Hook((Expression<Action>)(() => Saving.RunOnServerGameOver((Run)null, (GameEndingDef)null)), (Delegate)new Action<orig_Saving_RunOnServerGameOver, Run, GameEndingDef>(Saving_RunOnServerGameOver)).GenerateTrampoline<orig_Saving_RunOnServerGameOver>();
			Run.onRunDestroyGlobal += Run_onRunDestroyGlobal;
		}

		private static void Saving_RunOnServerGameOver(orig_Saving_RunOnServerGameOver orig, Run run, GameEndingDef ending)
		{
			_deleteSaveFileOnRunEnd = true;
			_lastRunInstance = run;
			_lastGameEndingDef = ending;
		}

		private static void deleteSaveFile()
		{
			_origRunOnServerGameOver(_lastRunInstance, _lastGameEndingDef);
		}

		private static void Run_onRunDestroyGlobal(Run _)
		{
			if (!_deleteSaveFileOnRunEnd)
			{
				return;
			}
			try
			{
				if (NetworkServer.active && !SuppressSaveFileDeletion)
				{
					deleteSaveFile();
				}
			}
			finally
			{
				_deleteSaveFileOnRunEnd = false;
				_lastRunInstance = null;
				_lastGameEndingDef = null;
			}
		}
	}
}