Decompiled source of Revive API v1.3.4

plugins/ReviveAPI.dll

Decompiled 2 weeks 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.Logging;
using HG.Reflection;
using HarmonyLib;
using IL.RoR2;
using IL.RoR2.Artifacts;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using On.RoR2;
using RoR2;
using RoR2.Artifacts;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: OptIn]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ReviveAPI")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+74e3eac968abd412176e0aefd8ceb676b02d1e53")]
[assembly: AssemblyProduct("ReviveAPI")]
[assembly: AssemblyTitle("ReviveAPI")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
[module: UnverifiableCode]
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 ReviveAPI
{
	[Serializable]
	[BepInPlugin("com.brynzananas.reviveapi", "Revive API", "1.3.4")]
	public class ReviveAPI : BaseUnityPlugin
	{
		public delegate bool CanReviveDelegate(CharacterMaster characterMaster);

		public delegate bool CanReviveNewDelegate(CharacterMaster characterMaster, out CanReviveInfo canReviveInfo);

		public delegate void OnReviveDelegate(CharacterMaster characterMaster);

		public delegate void OnReviveNewDelegate(CharacterMaster characterMaster, CanReviveInfo canReviveInfo);

		public class CanReviveInfo
		{
			public CanTakeResult canTakeResult;
		}

		public class CustomRevive
		{
			[Obsolete("Use canReviveNew instead")]
			public CanReviveDelegate canRevive;

			public CanReviveNewDelegate canReviveNew;

			public OnReviveDelegate onRevive;

			public OnReviveNewDelegate onReviveNew;

			public PendingOnRevive[] pendingOnRevives;

			public int priority;
		}

		public class PendingOnRevive
		{
			internal CharacterMaster characterMaster;

			public float timer;

			public OnReviveDelegate onReviveDelegate;
		}

		public const string ModGuid = "com.brynzananas.reviveapi";

		public const string ModName = "Revive API";

		public const string ModVer = "1.3.4";

		public const bool ENABLE_TEST = false;

		public static ManualLogSource ManualLogger;

		private static List<PendingOnRevive> pendingRevives = new List<PendingOnRevive>();

		private static List<CustomRevive> customRevives = new List<CustomRevive>();

		private bool hooksSet;

		private static CanReviveInfo canReviveInfoGlobal;

		private static CustomRevive customReviveGlobal;

		public static PendingOnRevive[] defaultPendingOnRevives
		{
			get
			{
				PendingOnRevive pendingOnRevive = new PendingOnRevive();
				pendingOnRevive.timer = 2f;
				pendingOnRevive.onReviveDelegate = SimpleRespawn;
				PendingOnRevive pendingOnRevive2 = pendingOnRevive;
				pendingOnRevive = new PendingOnRevive();
				pendingOnRevive.timer = 2f;
				pendingOnRevive.onReviveDelegate = SimpleRespawnSound;
				PendingOnRevive pendingOnRevive3 = pendingOnRevive;
				return new PendingOnRevive[2] { pendingOnRevive2, pendingOnRevive3 };
			}
		}

		public void Awake()
		{
			ManualLogger = ((BaseUnityPlugin)this).Logger;
			SetHooks();
		}

		public void FixedUpdate()
		{
			for (int i = 0; i < pendingRevives.Count; i++)
			{
				PendingOnRevive pendingOnRevive = pendingRevives[i];
				pendingOnRevive.timer -= Time.fixedDeltaTime;
				if (pendingOnRevive.timer <= 0f)
				{
					pendingRevives.Remove(pendingOnRevive);
					if (Object.op_Implicit((Object)(object)pendingOnRevive.characterMaster))
					{
						pendingOnRevive.onReviveDelegate?.Invoke(pendingOnRevive.characterMaster);
					}
				}
			}
		}

		public static void SimpleRespawn(CharacterMaster characterMaster)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = characterMaster.deathFootPosition;
			if (characterMaster.killedByUnsafeArea)
			{
				val = (Vector3)(((??)TeleportHelper.FindSafeTeleportDestination(characterMaster.deathFootPosition, characterMaster.bodyPrefab.GetComponent<CharacterBody>(), RoR2Application.rng)) ?? characterMaster.deathFootPosition);
			}
			characterMaster.Respawn(val, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f), true);
		}

		public static void SimpleRespawnSound(CharacterMaster characterMaster)
		{
			characterMaster.PlayExtraLifeSFX();
		}

		public void Destroy()
		{
			UnsetHooks();
		}

		private void SetHooks()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			if (!hooksSet)
			{
				TeamDeathArtifactManager.OnServerCharacterDeathGlobal += new Manipulator(TeamDeathArtifactManager_OnServerCharacterDeathGlobal);
				DoppelgangerInvasionManager.OnCharacterDeathGlobal += new Manipulator(DoppelgangerInvasionManager_OnCharacterDeathGlobal);
				CharacterMaster.IsDeadAndOutOfLivesServer += new Manipulator(CharacterMaster_IsDeadAndOutOfLivesServer);
				CharacterMaster.IsExtraLifePendingServer += new hook_IsExtraLifePendingServer(CharacterMaster_IsExtraLifePendingServer);
				CharacterMaster.TryReviveOnBodyDeath += new hook_TryReviveOnBodyDeath(CharacterMaster_TryReviveOnBodyDeath);
				hooksSet = true;
			}
		}

		private bool CharacterMaster_TryReviveOnBodyDeath(orig_TryReviveOnBodyDeath orig, CharacterMaster self, CharacterBody body)
		{
			if (CanReviveBeforeVanilla(self))
			{
				return ReviveBeforeVanilla(self);
			}
			bool flag = orig.Invoke(self, body);
			if (!flag && CanReviveAfterVanilla(self))
			{
				flag = ReviveAfterVanilla(self);
			}
			return flag;
		}

		private void UnsetHooks()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			if (hooksSet)
			{
				TeamDeathArtifactManager.OnServerCharacterDeathGlobal -= new Manipulator(TeamDeathArtifactManager_OnServerCharacterDeathGlobal);
				DoppelgangerInvasionManager.OnCharacterDeathGlobal -= new Manipulator(DoppelgangerInvasionManager_OnCharacterDeathGlobal);
				CharacterMaster.IsDeadAndOutOfLivesServer -= new Manipulator(CharacterMaster_IsDeadAndOutOfLivesServer);
				CharacterMaster.IsExtraLifePendingServer -= new hook_IsExtraLifePendingServer(CharacterMaster_IsExtraLifePendingServer);
				CharacterMaster.TryReviveOnBodyDeath -= new hook_TryReviveOnBodyDeath(CharacterMaster_TryReviveOnBodyDeath);
				hooksSet = false;
			}
		}

		private bool CharacterMaster_IsExtraLifePendingServer(orig_IsExtraLifePendingServer orig, CharacterMaster self)
		{
			bool flag = orig.Invoke(self);
			if (!flag)
			{
				flag = pendingRevives.Where((PendingOnRevive x) => (Object)(object)x.characterMaster == (Object)(object)self).ToArray().Length != 0;
			}
			return flag;
		}

		private void TeamDeathArtifactManager_OnServerCharacterDeathGlobal(ILContext iLContext)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Expected O, but got Unknown
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(iLContext);
			ILLabel val2 = null;
			if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, typeof(TeamDeathArtifactManager), "forceSpectatePrefab")
			}))
			{
				val2 = val.DefineLabel();
				val2.Target = val.Prev;
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " finding forceSpectatePrefab label IL Hook failed!"));
			}
			val = new ILCursor(iLContext);
			ILLabel beforeCheck = null;
			if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[5]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdfld(x, typeof(DamageReport), "victimMaster"),
				(Instruction x) => ILPatternMatchingExt.MatchCallvirt<CharacterMaster>(x, "get_playerCharacterMasterController"),
				(Instruction x) => ILPatternMatchingExt.MatchCall<Object>(x, "op_Implicit"),
				(Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref beforeCheck)
			}))
			{
				val.Emit(OpCodes.Ldarg_0);
				val.Emit(OpCodes.Ldfld, AccessTools.Field(typeof(DamageReport), "victimMaster"));
				val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)CanReviveBeforeVanilla);
				val.Emit(OpCodes.Brtrue_S, (object)beforeCheck);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " before IL Hook failed!"));
			}
			val = new ILCursor(iLContext);
			ILLabel afterCheck = null;
			if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[5]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdfld(x, typeof(DamageReport), "victimMaster"),
				(Instruction x) => ILPatternMatchingExt.MatchLdfld(x, typeof(CharacterMaster), "seekerSelfRevive"),
				(Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref afterCheck),
				(Instruction x) => ILPatternMatchingExt.MatchRet(x)
			}))
			{
				Instruction prev = val.Emit(OpCodes.Ldarg_0).Prev;
				val.Emit(OpCodes.Ldfld, AccessTools.Field(typeof(DamageReport), "victimMaster"));
				val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)CanReviveAfterVanilla);
				val.Emit(OpCodes.Brfalse_S, (object)val2);
				afterCheck.Target = prev;
				val.Emit(OpCodes.Ret);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " after IL Hook failed!"));
			}
		}

		private void CharacterMaster_IsDeadAndOutOfLivesServer(ILContext iLContext)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(iLContext);
			ILLabel iLLabel = null;
			if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, typeof(Items), "ExtraLife"),
				(Instruction x) => ILPatternMatchingExt.MatchCallvirt<Inventory>(x, "GetItemCountEffective"),
				(Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchBgt(x, ref iLLabel)
			}))
			{
				val.Emit(OpCodes.Ldarg_0);
				val.Emit(OpCodes.Ldc_I4_0);
				val.Emit(OpCodes.Ldc_I4_0);
				val.EmitDelegate<Func<CharacterMaster, bool, bool, bool>>((Func<CharacterMaster, bool, bool, bool>)CanReviveAndOrRevive);
				val.Emit(OpCodes.Brtrue_S, (object)iLLabel);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " IL Hook failed!"));
			}
		}

		private void DoppelgangerInvasionManager_OnCharacterDeathGlobal(ILContext iLContext)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Expected O, but got Unknown
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(iLContext);
			ILLabel returnLabel = null;
			if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[5]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, typeof(Items), "InvadingDoppelganger"),
				(Instruction x) => ILPatternMatchingExt.MatchCallvirt<Inventory>(x, "GetItemCountEffective"),
				(Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchBle(x, ref returnLabel)
			}))
			{
				val.Emit(OpCodes.Ldarg_1);
				val.Emit(OpCodes.Ldfld, AccessTools.Field(typeof(DamageReport), "victimMaster"));
				val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)CanReviveBeforeVanilla);
				val.Emit(OpCodes.Brtrue_S, (object)returnLabel);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " before IL Hook failed!"));
			}
			val = new ILCursor(iLContext);
			ILLabel iLLabel = null;
			if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[7]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 1),
				(Instruction x) => ILPatternMatchingExt.MatchLdfld(x, typeof(DamageReport), "victimBody"),
				(Instruction x) => ILPatternMatchingExt.MatchCallvirt<CharacterBody>(x, "get_equipmentSlot"),
				(Instruction x) => ILPatternMatchingExt.MatchCallvirt<EquipmentSlot>(x, "get_equipmentIndex"),
				(Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, typeof(Equipment), "HealAndRevive"),
				(Instruction x) => ILPatternMatchingExt.MatchCallvirt<EquipmentDef>(x, "get_equipmentIndex"),
				(Instruction x) => ILPatternMatchingExt.MatchBeq(x, ref iLLabel)
			}))
			{
				val.Emit(OpCodes.Ldarg_1);
				val.Emit(OpCodes.Ldfld, AccessTools.Field(typeof(DamageReport), "victimMaster"));
				val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)CanReviveAfterVanilla);
				val.Emit(OpCodes.Brtrue_S, (object)iLLabel);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " after IL Hook failed!"));
			}
		}

		private void CharacterMaster_OnBodyDeath(ILContext iLContext)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Unknown result type (might be due to invalid IL or missing references)
			//IL_044b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			ILCursor val = new ILCursor(iLContext);
			Instruction val2 = null;
			Instruction val3 = null;
			ILLabel ilLabel = null;
			int num = default(int);
			ILLabel val6 = default(ILLabel);
			if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchLdloca(x, ref num),
				(Instruction x) => ILPatternMatchingExt.MatchCall<Component>(x, "TryGetComponent"),
				(Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref val6)
			}))
			{
				val2 = val.Next;
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " IL hook 1 failed!"));
			}
			val = new ILCursor(iLContext);
			ILLabel val5 = default(ILLabel);
			if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[4]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 1),
				(Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, typeof(Buffs), "ExtraLifeBuff"),
				(Instruction x) => ILPatternMatchingExt.MatchCallvirt<CharacterBody>(x, "HasBuff"),
				(Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref val5)
			}))
			{
				val3 = val.Next;
				val.Emit(OpCodes.Ldarg_0);
				val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)CanReviveBeforeVanilla);
				val.Emit(OpCodes.Brfalse_S, val3);
				val.Emit(OpCodes.Ldarg_0);
				val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)ReviveBeforeVanilla);
				val.Emit(OpCodes.Brtrue_S, val2);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " IL hook 2 failed!"));
			}
			val = new ILCursor(iLContext);
			ILLabel val4 = default(ILLabel);
			if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[6]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloca(x, 5),
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchCall<CharacterMaster>(x, "get_inventory"),
				(Instruction x) => ILPatternMatchingExt.MatchLdloca(x, 1),
				(Instruction x) => ILPatternMatchingExt.MatchCall<ItemTransformation>(x, "TryTake"),
				(Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref val4)
			}) && val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[6]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdloca(x, 5),
				(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
				(Instruction x) => ILPatternMatchingExt.MatchCall<CharacterMaster>(x, "get_inventory"),
				(Instruction x) => ILPatternMatchingExt.MatchLdloca(x, 1),
				(Instruction x) => ILPatternMatchingExt.MatchCall<ItemTransformation>(x, "TryTake"),
				(Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref ilLabel)
			}))
			{
				Instruction target = ilLabel.Target;
				val.GotoLabel(ilLabel, (MoveType)0, false);
				ilLabel.Target = val.Emit(OpCodes.Ldarg_0).Prev;
				val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)CanReviveAfterVanilla);
				val.Emit(OpCodes.Brfalse_S, target);
				val.Emit(OpCodes.Ldarg_0);
				val.EmitDelegate<Func<CharacterMaster, bool>>((Func<CharacterMaster, bool>)ReviveAfterVanilla);
				val.Emit(OpCodes.Brtrue_S, val2);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)(((MemberReference)iLContext.Method).Name + " IL hook 3 failed!"));
			}
		}

		private static bool CanReviveBeforeVanilla(CharacterMaster characterMaster)
		{
			return CanRevive(characterMaster, customRevives.Where((CustomRevive item) => item.priority > 0).ToArray());
		}

		private static bool CanReviveAfterVanilla(CharacterMaster characterMaster)
		{
			return CanRevive(characterMaster, customRevives.Where((CustomRevive item) => item.priority <= 0).ToArray());
		}

		private static bool CanRevive(CharacterMaster characterMaster, CustomRevive[] customRevives)
		{
			foreach (CustomRevive customRevive in customRevives)
			{
				if (customRevive.canRevive != null && customRevive.canRevive(characterMaster))
				{
					return true;
				}
				if (customRevive.canReviveNew != null && customRevive.canReviveNew(characterMaster, out var canReviveInfo))
				{
					canReviveInfoGlobal = canReviveInfo;
					return true;
				}
			}
			return false;
		}

		private static bool ReviveBeforeVanilla(CharacterMaster characterMaster)
		{
			return Revive(characterMaster, customRevives.Where((CustomRevive item) => item.priority > 0).ToArray());
		}

		private static bool ReviveAfterVanilla(CharacterMaster characterMaster)
		{
			return Revive(characterMaster, customRevives.Where((CustomRevive item) => item.priority <= 0).ToArray());
		}

		private static bool Revive(CharacterMaster characterMaster, CustomRevive[] customRevives)
		{
			foreach (CustomRevive customRevive in customRevives)
			{
				if (customRevive.canRevive != null && customRevive.canRevive(characterMaster))
				{
					customRevive.onRevive?.Invoke(characterMaster);
					if (customRevive.pendingOnRevives != null)
					{
						HandlePendingOnRevives(customRevive, characterMaster);
					}
					return true;
				}
				if (customRevive.canReviveNew != null && customRevive.canReviveNew(characterMaster, out canReviveInfoGlobal))
				{
					customRevive.onReviveNew?.Invoke(characterMaster, canReviveInfoGlobal);
					if (customRevive.pendingOnRevives != null)
					{
						HandlePendingOnRevives(customRevive, characterMaster);
					}
					return true;
				}
			}
			return false;
		}

		private static void HandlePendingOnRevives(CustomRevive customRevive, CharacterMaster characterMaster)
		{
			PendingOnRevive[] pendingOnRevives = customRevive.pendingOnRevives;
			foreach (PendingOnRevive pendingOnRevive in pendingOnRevives)
			{
				PendingOnRevive item = new PendingOnRevive
				{
					timer = Mathf.Max(1f, pendingOnRevive.timer),
					characterMaster = characterMaster,
					onReviveDelegate = pendingOnRevive.onReviveDelegate
				};
				pendingRevives.Add(item);
			}
		}

		private static bool CanReviveAndOrRevive(CharacterMaster characterMaster, bool reverse, bool onRevive)
		{
			bool flag = reverse;
			foreach (CustomRevive customRevife in customRevives)
			{
				if (customRevife.canRevive == null || !customRevife.canRevive(characterMaster))
				{
					continue;
				}
				flag = !flag;
				if (!onRevive)
				{
					break;
				}
				customRevife.onRevive?.Invoke(characterMaster);
				if (customRevife.pendingOnRevives != null)
				{
					PendingOnRevive[] pendingOnRevives = customRevife.pendingOnRevives;
					foreach (PendingOnRevive pendingOnRevive in pendingOnRevives)
					{
						PendingOnRevive item = new PendingOnRevive
						{
							timer = Mathf.Max(1f, pendingOnRevive.timer),
							characterMaster = characterMaster,
							onReviveDelegate = pendingOnRevive.onReviveDelegate
						};
						pendingRevives.Add(item);
					}
				}
				break;
			}
			return flag;
		}

		public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate, int priority)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canReviveNew = canReviveNewDelegate,
				pendingOnRevives = defaultPendingOnRevives,
				priority = priority
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate, OnReviveNewDelegate onReviveNewDelegate, int priority)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canReviveNew = canReviveNewDelegate,
				onReviveNew = onReviveNewDelegate,
				pendingOnRevives = null,
				priority = priority
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate, OnReviveNewDelegate onReviveNewDelegate, PendingOnRevive[] pendingOnRevives, int priority)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canReviveNew = canReviveNewDelegate,
				onReviveNew = onReviveNewDelegate,
				pendingOnRevives = pendingOnRevives,
				priority = priority
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canReviveNew = canReviveNewDelegate,
				pendingOnRevives = defaultPendingOnRevives,
				priority = -1
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate, OnReviveNewDelegate onReviveNewDelegate)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canReviveNew = canReviveNewDelegate,
				onReviveNew = onReviveNewDelegate,
				pendingOnRevives = null,
				priority = -1
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate, PendingOnRevive[] pendingOnRevives)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canReviveNew = canReviveNewDelegate,
				pendingOnRevives = pendingOnRevives,
				priority = -1
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveNewDelegate canReviveNewDelegate, OnReviveNewDelegate onReviveNewDelegate, PendingOnRevive[] pendingOnRevives)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canReviveNew = canReviveNewDelegate,
				onReviveNew = onReviveNewDelegate,
				pendingOnRevives = pendingOnRevives,
				priority = -1
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, int priority)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canRevive = canReviveDelegate,
				pendingOnRevives = defaultPendingOnRevives,
				priority = priority
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, OnReviveDelegate onReviveDelegate, int priority)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canRevive = canReviveDelegate,
				onRevive = onReviveDelegate,
				pendingOnRevives = defaultPendingOnRevives,
				priority = priority
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, PendingOnRevive[] pendingOnRevives, int priority)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canRevive = canReviveDelegate,
				pendingOnRevives = pendingOnRevives,
				priority = priority
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, OnReviveDelegate onReviveDelegate, PendingOnRevive[] pendingOnRevives, int priority)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canRevive = canReviveDelegate,
				onRevive = onReviveDelegate,
				pendingOnRevives = pendingOnRevives,
				priority = priority
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveDelegate canReviveDelegate)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canRevive = canReviveDelegate,
				pendingOnRevives = defaultPendingOnRevives,
				priority = -1
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, OnReviveDelegate onReviveDelegate)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canRevive = canReviveDelegate,
				onRevive = onReviveDelegate,
				pendingOnRevives = defaultPendingOnRevives,
				priority = -1
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, PendingOnRevive[] pendingOnRevives)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canRevive = canReviveDelegate,
				pendingOnRevives = pendingOnRevives,
				priority = -1
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CanReviveDelegate canReviveDelegate, OnReviveDelegate onReviveDelegate, PendingOnRevive[] pendingOnRevives)
		{
			CustomRevive customRevive = new CustomRevive
			{
				canRevive = canReviveDelegate,
				onRevive = onReviveDelegate,
				pendingOnRevives = pendingOnRevives,
				priority = -1
			};
			AddCustomRevive(customRevive);
		}

		public static void AddCustomRevive(CustomRevive customRevive)
		{
			customRevives.Add(customRevive);
			customRevives = customRevives.OrderByDescending((CustomRevive x) => x.priority).ToList();
		}
	}
}