Decompiled source of ReviveCompany v1.4.0

ReviveCompany.dll

Decompiled 5 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using OPJosMod.ReviveCompany.CustomRpc;
using OPJosMod.ReviveCompany.Patches;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("OPJosMod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OPJosMod")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("70095872-b952-4e27-bbc4-3d70d0238f39")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace OPJosMod.ReviveCompany
{
	public static class ConfigVariables
	{
		public static float reviveTime;

		public static bool reviveTeleportedBodies;

		public static Key ReviveButton;

		public static bool CanPickUpBodies;

		public static float DeadPlayerWeight;

		public static int ReviveToHealth;

		public static bool LimitedRevives;

		public static float RevivesPerLevelMultiplier;

		public static int HardAmountOfLives;

		public static int ExtraHealthLostPerRevive;

		public static bool InfiniteReviveTime;

		public static int TimeUnitlCantBeRevived;
	}
	public static class GeneralUtil
	{
		private static ManualLogSource mls;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}

		public static Vector3 StringToVector3(string str)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			string[] array = str.Trim('(', ')').Split(new char[1] { ',' });
			float num = float.Parse(array[0]);
			float num2 = float.Parse(array[1]);
			float num3 = float.Parse(array[2]);
			return new Vector3(num, num2, num3);
		}

		public static RagdollGrabbableObject GetClosestDeadBody(Vector3 position)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			RagdollGrabbableObject result = null;
			float num = float.MaxValue;
			RagdollGrabbableObject[] array = Object.FindObjectsOfType<RagdollGrabbableObject>();
			RagdollGrabbableObject[] array2 = array;
			foreach (RagdollGrabbableObject val in array2)
			{
				float num2 = Vector3.Distance(((Component)val).transform.position, position);
				if (num2 < num)
				{
					result = val;
					num = num2;
				}
			}
			return result;
		}

		public static PlayerControllerB GetClosestAlivePlayer(Vector3 position)
		{
			//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)
			PlayerControllerB result = null;
			float num = float.MaxValue;
			PlayerControllerB[] allPlayerScripts = RoundManager.Instance.playersManager.allPlayerScripts;
			PlayerControllerB[] array = allPlayerScripts;
			foreach (PlayerControllerB val in array)
			{
				if (!val.isPlayerDead)
				{
					float num2 = Vector3.Distance(((Component)val).transform.position, position);
					if (num2 < num)
					{
						result = val;
						num = num2;
					}
				}
			}
			return result;
		}

		public static string simplifyObjectNames(string ogName)
		{
			string text = ogName;
			int num = text.IndexOf("(");
			if (num != -1)
			{
				text = text.Substring(0, num).Trim();
			}
			return text;
		}

		public static void RevivePlayer(int playerId)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Expected O, but got Unknown
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Expected O, but got Unknown
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e7: Expected O, but got Unknown
			//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0404: Expected O, but got Unknown
			//IL_053f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0423: Unknown result type (might be due to invalid IL or missing references)
			//IL_042e: Expected O, but got Unknown
			//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d6: Expected O, but got Unknown
			//IL_05ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b5: Expected O, but got Unknown
			//IL_060f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0619: Expected O, but got Unknown
			if (playerId >= RoundManager.Instance.playersManager.allPlayerScripts.Length || playerId < 0)
			{
				Debug.Log((object)$"ReiveCompanyERROR: error when trying to revive player {playerId} as it is outside the range of the allPlayerScripts array");
				return;
			}
			PlayerControllerB val = RoundManager.Instance.playersManager.allPlayerScripts[playerId];
			if ((Object)(object)val != (Object)null && !val.isPlayerDead)
			{
				Debug.Log((object)$"ReiveCompanyERROR: error when trying to revive player {playerId} player is already alive! do nothing more");
				return;
			}
			Vector3 val2 = val.serverPlayerPosition;
			if ((Object)(object)val.deadBody != (Object)null && (Object)(object)((Component)val.deadBody).transform != (Object)null)
			{
				_ = ((Component)val.deadBody).transform.position;
				if (true)
				{
					val2 = ((Component)val.deadBody).transform.position;
					PlayerControllerB closestAlivePlayer = GetClosestAlivePlayer(((Component)val.deadBody).transform.position);
					if ((Object)(object)closestAlivePlayer != (Object)null && Vector3.Distance(val2, ((Component)closestAlivePlayer).transform.position) > 7f)
					{
						val2 = ((Component)closestAlivePlayer).transform.position;
					}
				}
			}
			bool isInsideFactory = false;
			PlayerControllerB closestAlivePlayer2 = GetClosestAlivePlayer(((Component)val.deadBody).transform.position);
			if ((Object)(object)closestAlivePlayer2 != (Object)null)
			{
				isInsideFactory = closestAlivePlayer2.isInsideFactory;
			}
			StartOfRound instance = StartOfRound.Instance;
			instance.livingPlayers++;
			StartOfRound.Instance.allPlayersDead = false;
			StartOfRound.Instance.UpdatePlayerVoiceEffects();
			GlobalVariables.RemainingRevives--;
			if (GlobalVariables.RemainingRevives < 100)
			{
				HUDManager.Instance.DisplayTip(val.playerUsername + " was revived", $"{GlobalVariables.RemainingRevives} revives remain!", false, false, "LC_Tip1");
			}
			int num = (int)val.playerClientId;
			val.ResetPlayerBloodObjects(val.isPlayerDead);
			val.isClimbingLadder = false;
			val.ResetZAndXRotation();
			((Collider)val.thisController).enabled = true;
			val.health = ConfigVariables.ReviveToHealth;
			val.disableLookInput = false;
			if (val.isPlayerDead)
			{
				val.isPlayerDead = false;
				val.isPlayerControlled = true;
				val.isInElevator = true;
				val.isInHangarShipRoom = true;
				val.isInsideFactory = isInsideFactory;
				val.TeleportPlayer(val2, false, 0f, false, true);
				val.setPositionOfDeadPlayer = false;
				val.DisablePlayerModel(StartOfRound.Instance.allPlayerObjects[num], true, true);
				((Behaviour)val.helmetLight).enabled = false;
				val.Crouch(false);
				val.criticallyInjured = false;
				if ((Object)val.playerBodyAnimator != (Object)null)
				{
					val.playerBodyAnimator.SetBool("Limp", false);
				}
				val.bleedingHeavily = false;
				val.activatingItem = false;
				val.twoHanded = false;
				val.inSpecialInteractAnimation = false;
				val.disableSyncInAnimation = false;
				val.inAnimationWithEnemy = null;
				val.holdingWalkieTalkie = false;
				val.speakingToWalkieTalkie = false;
				val.isSinking = false;
				val.isUnderwater = false;
				val.sinkingValue = 0f;
				val.statusEffectAudio.Stop();
				val.DisableJetpackControlsLocally();
				val.health = ConfigVariables.ReviveToHealth;
				val.mapRadarDotAnimator.SetBool("dead", false);
				val.hasBegunSpectating = false;
				val.hinderedMultiplier = 1f;
				val.isMovementHindered = 0;
				val.sourcesCausingSinking = 0;
				val.reverbPreset = StartOfRound.Instance.shipReverb;
			}
			SoundManager.Instance.earsRingingTimer = 0f;
			val.voiceMuffledByEnemy = false;
			SoundManager.Instance.playerVoicePitchTargets[num] = 1f;
			SoundManager.Instance.SetPlayerPitch(1f, num);
			if ((Object)val.currentVoiceChatIngameSettings == (Object)null)
			{
				StartOfRound.Instance.RefreshPlayerVoicePlaybackObjects();
			}
			if ((Object)val.currentVoiceChatIngameSettings != (Object)null)
			{
				if ((Object)val.currentVoiceChatIngameSettings.voiceAudio == (Object)null)
				{
					val.currentVoiceChatIngameSettings.InitializeComponents();
				}
				if ((Object)val.currentVoiceChatIngameSettings.voiceAudio == (Object)null)
				{
					return;
				}
				((Component)val.currentVoiceChatIngameSettings.voiceAudio).GetComponent<OccludeAudio>().overridingLowPass = false;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if (localPlayerController.playerClientId == val.playerClientId)
			{
				GlobalVariables.AmountOfTimesRevived++;
				int num2 = ConfigVariables.ReviveToHealth - GlobalVariables.AmountOfTimesRevived * ConfigVariables.ExtraHealthLostPerRevive;
				localPlayerController.bleedingHeavily = false;
				localPlayerController.criticallyInjured = false;
				localPlayerController.playerBodyAnimator.SetBool("Limp", false);
				localPlayerController.health = num2;
				localPlayerController.spectatedPlayerScript = null;
				((Behaviour)HUDManager.Instance.audioListenerLowPass).enabled = false;
				StartOfRound.Instance.SetSpectateCameraToGameOverMode(false, localPlayerController);
				StartOfRound.Instance.SetPlayerObjectExtrapolate(false);
				HUDManager.Instance.UpdateHealthUI(num2, true);
				HUDManager.Instance.gasHelmetAnimator.SetBool("gasEmitting", false);
				HUDManager.Instance.RemoveSpectateUI();
				HUDManager.Instance.gameOverAnimator.SetTrigger("revive");
			}
			RagdollGrabbableObject closestDeadBody = GetClosestDeadBody(((Component)val).transform.position);
			if ((Object)(object)closestDeadBody != (Object)null)
			{
				if (!((GrabbableObject)closestDeadBody).isHeld)
				{
					if (((NetworkBehaviour)StartOfRound.Instance).IsServer)
					{
						if (((NetworkBehaviour)closestDeadBody).NetworkObject.IsSpawned)
						{
							((NetworkBehaviour)closestDeadBody).NetworkObject.Despawn(true);
						}
						else
						{
							Object.Destroy((Object)((Component)closestDeadBody).gameObject);
						}
					}
				}
				else if (((GrabbableObject)closestDeadBody).isHeld && (Object)((GrabbableObject)closestDeadBody).playerHeldBy != (Object)null)
				{
					((GrabbableObject)closestDeadBody).playerHeldBy.DropAllHeldItems(true, false);
				}
				if ((Object)(object)closestDeadBody.ragdoll != (Object)null)
				{
					Object.Destroy((Object)((Component)closestDeadBody.ragdoll).gameObject);
				}
			}
			if (localPlayerController.isPlayerDead)
			{
				HUDManager.Instance.UpdateBoxesSpectateUI();
			}
		}

		public static void ResetAllPlayerInfos()
		{
			GlobalVariables.PlayerInfos.Clear();
			PlayerControllerB[] allPlayerScripts = RoundManager.Instance.playersManager.allPlayerScripts;
			foreach (PlayerControllerB val in allPlayerScripts)
			{
				GlobalVariables.PlayerInfos.Add(new PlayerInfo
				{
					PlayerId = (int)val.playerClientId
				});
			}
		}

		public static bool HasPlayerTeleported(int playerClientId)
		{
			int num = GlobalVariables.PlayerInfos.FindIndex((PlayerInfo p) => p.PlayerId == playerClientId);
			if (num != -1)
			{
				return GlobalVariables.PlayerInfos[num].HasBeenTeleported;
			}
			return false;
		}

		public static void SetPlayerAsTeleported(int playerClientId)
		{
			int num = GlobalVariables.PlayerInfos.FindIndex((PlayerInfo p) => p.PlayerId == playerClientId);
			if (num != -1)
			{
				GlobalVariables.PlayerInfos[num].HasBeenTeleported = true;
			}
		}

		public static void SetPlayerDiedAt(int playerClientId)
		{
			int num = GlobalVariables.PlayerInfos.FindIndex((PlayerInfo p) => p.PlayerId == playerClientId);
			if (num != -1)
			{
				GlobalVariables.PlayerInfos[num].TimeDiedAt = Time.time;
			}
		}

		public static float GetPlayersDiedAtTime(int playerClientId)
		{
			int num = GlobalVariables.PlayerInfos.FindIndex((PlayerInfo p) => p.PlayerId == playerClientId);
			if (num != -1)
			{
				return GlobalVariables.PlayerInfos[num].TimeDiedAt;
			}
			return Time.time;
		}
	}
	public static class GlobalVariables
	{
		public static bool ModActivated = false;

		public static List<PlayerInfo> PlayerInfos = new List<PlayerInfo>();

		public static int RemainingRevives = int.MaxValue;

		public static int AmountOfTimesRevived = 0;
	}
	public class PlayerInfo
	{
		public int PlayerId { get; set; }

		public bool HasBeenTeleported { get; set; }

		public float TimeDiedAt { get; set; }
	}
	[BepInPlugin("OpJosMod.ReviveCompany", "ReviveCompany", "1.4.0")]
	public class OpJosMod : BaseUnityPlugin
	{
		private const string modGUID = "OpJosMod.ReviveCompany";

		private const string modName = "ReviveCompany";

		private const string modVersion = "1.4.0";

		private readonly Harmony harmony = new Harmony("OpJosMod.ReviveCompany");

		private static OpJosMod Instance;

		internal ManualLogSource mls;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			mls = Logger.CreateLogSource("OpJosMod.ReviveCompany");
			setupConfig();
			PatchesForRPC.SetLogSource(mls);
			RpcMessageHandler.SetLogSource(mls);
			CompleteRecievedTasks.SetLogSource(mls);
			ResponseHandler.SetLogSource(mls);
			PlayerControllerBPatch.SetLogSource(mls);
			ShipTeleporterPatch.SetLogSource(mls);
			StartOfRoundPatch.SetLogSource(mls);
			RagdollGrabbableObjectPatch.SetLogSource(mls);
			GeneralUtil.SetLogSource(mls);
			harmony.PatchAll();
		}

		private void setupConfig()
		{
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<float> val = ((BaseUnityPlugin)this).Config.Bind<float>("Revive Time", "ReviveTime", 5f, "How long it takes to revive someone");
			ConfigEntry<Key> val2 = ((BaseUnityPlugin)this).Config.Bind<Key>("ReviveButton", "ReviveButton", (Key)32, "Button Used to Revive Players");
			ConfigEntry<bool> val3 = ((BaseUnityPlugin)this).Config.Bind<bool>("Can Pick Up Bodies", "CanPickUpBodies", true, "Toggle if you can pick up bodies.");
			ConfigEntry<float> val4 = ((BaseUnityPlugin)this).Config.Bind<float>("Dead Body Weight Multiplier", "DeadBodyWeight", 3.25f, "How heavy are the dead players.");
			ConfigEntry<bool> val5 = ((BaseUnityPlugin)this).Config.Bind<bool>("Can Revive Teleported Bodies", "CanReviveTeleportedBodies", false, "Toggle for if you are able to revive dead players you teleport back to the ship");
			ConfigEntry<int> val6 = ((BaseUnityPlugin)this).Config.Bind<int>("Health you revive with.", "HealthYouReviveWith", 25, "How much health you revive with.");
			ConfigEntry<int> val7 = ((BaseUnityPlugin)this).Config.Bind<int>("Extra Health Lost Per Revive", "ExtraHealthLostPerRevive", 5, "If player is revived more than once per level, revive with this much less HP each time");
			ConfigEntry<bool> val8 = ((BaseUnityPlugin)this).Config.Bind<bool>("Limit amount of revives", "LimitAmountOfRevives", true, "do you want to have limited revives?");
			ConfigEntry<float> val9 = ((BaseUnityPlugin)this).Config.Bind<float>("Revives Per Level Multiplier", "RevivesPerLevelMultiplier", 1.25f, "How many revives you get per level, mulitplied by players in game. ex) value set to 2 and have 4 players then you get 8 revives.");
			ConfigEntry<int> val10 = ((BaseUnityPlugin)this).Config.Bind<int>("Set Amount of Revives", "SetAmountOfRevives", 0, "Set amount of revives per level. If not at 0 This will override the revive amount being set by the (Revives Per Level Multiplier) setting");
			ConfigEntry<bool> val11 = ((BaseUnityPlugin)this).Config.Bind<bool>("Infinite Revive Time", "InfiniteReviveTime", false, "Can you alwasy revive someone no longer how long they have been dead?");
			ConfigEntry<int> val12 = ((BaseUnityPlugin)this).Config.Bind<int>("Time Until Cant Be Revived", "TimeUntilCantBeRevived", 120, "How long someone can be dead for and still be revived in seconds");
			ConfigVariables.reviveTime = val.Value;
			ConfigVariables.ReviveButton = val2.Value;
			ConfigVariables.CanPickUpBodies = val3.Value;
			ConfigVariables.DeadPlayerWeight = val4.Value;
			ConfigVariables.reviveTeleportedBodies = val5.Value;
			ConfigVariables.ReviveToHealth = val6.Value;
			ConfigVariables.LimitedRevives = val8.Value;
			ConfigVariables.RevivesPerLevelMultiplier = val9.Value;
			ConfigVariables.HardAmountOfLives = val10.Value;
			ConfigVariables.ExtraHealthLostPerRevive = val7.Value;
			ConfigVariables.InfiniteReviveTime = val11.Value;
			ConfigVariables.TimeUnitlCantBeRevived = val12.Value;
		}
	}
}
namespace OPJosMod.ReviveCompany.Utils
{
	public class ReflectionUtils
	{
		public static void InvokeMethod(object obj, string methodName, object[] parameters)
		{
			Type type = obj.GetType();
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			method.Invoke(obj, parameters);
		}

		public static void InvokeMethod(object obj, Type forceType, string methodName, object[] parameters)
		{
			MethodInfo method = forceType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			method.Invoke(obj, parameters);
		}

		public static void SetPropertyValue(object obj, string propertyName, object value)
		{
			Type type = obj.GetType();
			PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			property.SetValue(obj, value);
		}

		public static T InvokeMethod<T>(object obj, string methodName, object[] parameters)
		{
			Type type = obj.GetType();
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			return (T)method.Invoke(obj, parameters);
		}

		public static T GetFieldValue<T>(object obj, string fieldName)
		{
			Type type = obj.GetType();
			FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			return (T)field.GetValue(obj);
		}

		public static void SetFieldValue(object obj, string fieldName, object value)
		{
			Type type = obj.GetType();
			FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			field.SetValue(obj, value);
		}
	}
}
namespace OPJosMod.ReviveCompany.Patches
{
	[HarmonyPatch(typeof(RagdollGrabbableObject))]
	internal class RagdollGrabbableObjectPatch
	{
		private static ManualLogSource mls;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}

		[HarmonyPatch("Start")]
		[HarmonyPrefix]
		private static void patchStart(RagdollGrabbableObject __instance)
		{
			if (GlobalVariables.ModActivated)
			{
				((GrabbableObject)__instance).itemProperties.weight = ConfigVariables.DeadPlayerWeight;
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatch
	{
		private static ManualLogSource mls;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}

		[HarmonyPatch("EndOfGame")]
		[HarmonyPrefix]
		private static void patchEndOfGame()
		{
			if (GlobalVariables.ModActivated)
			{
				mls.LogMessage((object)"reset bodies teleported list");
				GeneralUtil.ResetAllPlayerInfos();
			}
		}

		[HarmonyPatch("openingDoorsSequence")]
		[HarmonyPrefix]
		private static void patchOpeningDoorsSequence()
		{
			if (GlobalVariables.ModActivated)
			{
				mls.LogMessage((object)"round starting, reseting allowed revive count");
				GeneralUtil.ResetAllPlayerInfos();
				setStartingRevives();
			}
		}

		private static void setStartingRevives()
		{
			int num = RoundManager.Instance.playersManager.allPlayerScripts.Where((PlayerControllerB x) => x.isPlayerControlled).Count();
			GlobalVariables.AmountOfTimesRevived = 0;
			if (ConfigVariables.LimitedRevives)
			{
				if (ConfigVariables.HardAmountOfLives != 0)
				{
					GlobalVariables.RemainingRevives = ConfigVariables.HardAmountOfLives;
				}
				else
				{
					GlobalVariables.RemainingRevives = Mathf.RoundToInt((float)num * ConfigVariables.RevivesPerLevelMultiplier);
				}
			}
			else
			{
				GlobalVariables.RemainingRevives = int.MaxValue;
			}
		}
	}
	[HarmonyPatch(typeof(ShipTeleporter))]
	internal class ShipTeleporterPatch
	{
		private static ManualLogSource mls;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}

		[HarmonyPatch("beamUpPlayer")]
		[HarmonyPrefix]
		private static void patchbeamUpPlayer()
		{
			if (GlobalVariables.ModActivated)
			{
				PlayerControllerB targetedPlayer = StartOfRound.Instance.mapScreen.targetedPlayer;
				if (!((Object)(object)targetedPlayer == (Object)null) && !((Object)(object)targetedPlayer.redirectToEnemy != (Object)null) && !((Object)(object)targetedPlayer.deadBody == (Object)null) && targetedPlayer.isPlayerDead)
				{
					GeneralUtil.SetPlayerAsTeleported((int)targetedPlayer.playerClientId);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerControllerBPatch
	{
		private static ManualLogSource mls;

		private static int interactableObjectsMask = 832;

		private static float StartedReviveAt = Time.time;

		private static bool StartedRevive = false;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}

		[HarmonyPatch("Interact_performed")]
		[HarmonyPrefix]
		private static bool interact_performedPatch(PlayerControllerB __instance)
		{
			if (!GlobalVariables.ModActivated)
			{
				return true;
			}
			if (ConfigVariables.CanPickUpBodies)
			{
				return true;
			}
			if (((NetworkBehaviour)__instance).IsOwner && !__instance.isPlayerDead && (!((NetworkBehaviour)__instance).IsServer || __instance.isHostPlayerObject) && !canUse(__instance))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch("KillPlayerClientRpc")]
		[HarmonyPrefix]
		private static void killPlayerClientRpcPatch(PlayerControllerB __instance, ref int playerId)
		{
			if (GlobalVariables.ModActivated)
			{
				GeneralUtil.SetPlayerDiedAt(playerId);
			}
		}

		[HarmonyPatch("SetHoverTipAndCurrentInteractTrigger")]
		[HarmonyPostfix]
		private static void setHoverTipAndCurrentInteractTriggerPatch(PlayerControllerB __instance)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if (!GlobalVariables.ModActivated)
			{
				return;
			}
			if (!canUse(__instance) && ((TMP_Text)__instance.cursorTip).text != "")
			{
				if (((ButtonControl)Keyboard.current[ConfigVariables.ReviveButton]).isPressed)
				{
					if (!StartedRevive)
					{
						StartedRevive = true;
						StartedReviveAt = Time.time;
					}
					else if (Time.time - StartedReviveAt > ConfigVariables.reviveTime)
					{
						RagdollGrabbableObject closestDeadBody = GeneralUtil.GetClosestDeadBody(((Component)__instance).transform.position);
						if (!canRevive(closestDeadBody))
						{
							((TMP_Text)__instance.cursorTip).text = "[Can't Revive Player!]";
							return;
						}
						StartedRevive = false;
						RpcMessage message = new RpcMessage(MessageTasks.RevivePlayer, closestDeadBody.ragdoll.playerScript.playerClientId.ToString(), (int)__instance.playerClientId, MessageCodes.Request);
						RpcMessageHandler.SendRpcMessage(message);
						ResponseHandler.SentMessageNeedResponses(message);
						GeneralUtil.RevivePlayer((int)closestDeadBody.ragdoll.playerScript.playerClientId);
						RpcMessage message2 = new RpcMessage(MessageTasks.TurnOffGhostMode, closestDeadBody.ragdoll.playerScript.playerClientId.ToString(), (int)__instance.playerClientId, MessageCodes.Request);
						RpcMessageHandler.SendRpcMessage(message2);
					}
					((TMP_Text)__instance.cursorTip).text = $"[Reviving! {(int)Mathf.Round(Time.time - StartedReviveAt)}/{ConfigVariables.reviveTime}s]";
					return;
				}
				if (ConfigVariables.InfiniteReviveTime)
				{
					((TMP_Text)__instance.cursorTip).text = $"[Hold {ConfigVariables.ReviveButton} to revive!]";
				}
				else
				{
					RagdollGrabbableObject closestDeadBody2 = GeneralUtil.GetClosestDeadBody(((Component)__instance).transform.position);
					double num = Math.Round((float)ConfigVariables.TimeUnitlCantBeRevived - (Time.time - GeneralUtil.GetPlayersDiedAtTime((int)closestDeadBody2.ragdoll.playerScript.playerClientId)));
					if (num > 0.0)
					{
						((TMP_Text)__instance.cursorTip).text = $"[Hold {ConfigVariables.ReviveButton} to revive!] {num}s Left!";
					}
					else
					{
						((TMP_Text)__instance.cursorTip).text = "0 Time Left!";
					}
				}
				StartedRevive = false;
			}
			else
			{
				StartedRevive = false;
			}
		}

		private static bool canUse(PlayerControllerB __instance)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			Ray val = default(Ray);
			((Ray)(ref val))..ctor(((Component)__instance.gameplayCamera).transform.position, ((Component)__instance.gameplayCamera).transform.forward);
			RaycastHit val2 = default(RaycastHit);
			Physics.Raycast(val, ref val2, __instance.grabDistance, interactableObjectsMask);
			Collider collider = ((RaycastHit)(ref val2)).collider;
			GrabbableObject val3 = ((collider != null) ? ((Component)collider).GetComponent<GrabbableObject>() : null);
			if ((Object)(object)val3 != (Object)null)
			{
				string text = GeneralUtil.simplifyObjectNames(((Object)val3).name);
				if (text == "RagdollGrabbableObject")
				{
					return false;
				}
			}
			return true;
		}

		private static bool canRevive(RagdollGrabbableObject revivingBody)
		{
			if (GlobalVariables.RemainingRevives <= 0)
			{
				return false;
			}
			if ((Object)(object)revivingBody != (Object)null && (Object)(object)revivingBody.ragdoll != (Object)null && (Object)(object)revivingBody.ragdoll.playerScript != (Object)null && GameNetworkManager.Instance.localPlayerController.playerClientId == revivingBody.ragdoll.playerScript.playerClientId)
			{
				return false;
			}
			int playerClientId = (int)revivingBody.ragdoll.playerScript.playerClientId;
			if (GeneralUtil.HasPlayerTeleported(playerClientId) && !ConfigVariables.reviveTeleportedBodies)
			{
				return false;
			}
			mls.LogInfo((object)(Time.time + " | " + GeneralUtil.GetPlayersDiedAtTime(playerClientId)));
			if (Time.time - GeneralUtil.GetPlayersDiedAtTime(playerClientId) > (float)ConfigVariables.TimeUnitlCantBeRevived && !ConfigVariables.InfiniteReviveTime)
			{
				return false;
			}
			return true;
		}
	}
}
namespace OPJosMod.ReviveCompany.CustomRpc
{
	public static class ResponseHandler
	{
		private static ManualLogSource mls;

		private static float LastSendTime;

		private static RpcMessage ResendMessageMessage;

		private static bool StartWaitForResend;

		private static int TotalResponses;

		private static int TotalSentMessages;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}

		public static void RecievedResponse(MessageTasks messageTask)
		{
			if (messageTask == MessageTasks.RevivePlayer && !((Object)(object)StartOfRound.Instance == (Object)null) && StartOfRound.Instance.allPlayerScripts != null)
			{
				TotalResponses++;
			}
		}

		public static void SentMessageNeedResponses(RpcMessage message)
		{
			LastSendTime = Time.time;
			ResendMessageMessage = message;
			StartWaitForResend = true;
			TotalResponses = 0;
			TotalSentMessages = 0;
		}

		public static void CalculateIfShouldResend()
		{
			if (ResendMessageMessage == null || ResendMessageMessage.Task != MessageTasks.RevivePlayer || !StartWaitForResend || !(Time.time - LastSendTime > 2f))
			{
				return;
			}
			if (TotalSentMessages > 4)
			{
				mls.LogError((object)"No longer retrying message send as it has already sent 5 extra times.");
				LastSendTime = 0f;
				StartWaitForResend = false;
				TotalResponses = 0;
				TotalSentMessages = 0;
				return;
			}
			int num = RoundManager.Instance.playersManager.allPlayerScripts.Where((PlayerControllerB x) => !x.playerUsername.Contains("Player")).ToList().Count();
			mls.LogMessage((object)$"TotalResponses:{TotalResponses}, playerCount:{num}");
			if (TotalResponses > num - 2 || num - 2 < 0)
			{
				LastSendTime = 0f;
				StartWaitForResend = false;
				TotalResponses = 0;
				TotalSentMessages = 0;
			}
			else
			{
				mls.LogMessage((object)"resending revive message as dont have enough responses");
				TotalSentMessages++;
				LastSendTime = Time.time;
				RpcMessageHandler.SendRpcMessage(ResendMessageMessage);
				ResendMessageMessage.Task = MessageTasks.TurnOffGhostMode;
				RpcMessageHandler.SendRpcMessage(ResendMessageMessage);
				ResendMessageMessage.Task = MessageTasks.RevivePlayer;
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerControllerBPatchResponseHandler
	{
		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		private static void patchUpdate(PlayerControllerB __instance)
		{
			if (GlobalVariables.ModActivated && ((NetworkBehaviour)__instance).IsOwner)
			{
				ResponseHandler.CalculateIfShouldResend();
			}
		}
	}
	public static class CompleteRecievedTasks
	{
		private static ManualLogSource mls;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}

		public static void ModActivated(string modName)
		{
			if (mls.SourceName == modName)
			{
				mls.LogMessage((object)"Mod Activated");
				GlobalVariables.ModActivated = true;
			}
		}

		public static void RevivePlayer(string playerIdString)
		{
			if (int.TryParse(playerIdString, out var result))
			{
				GeneralUtil.RevivePlayer(result);
			}
			else
			{
				mls.LogError((object)("Error: Invalid player ID '" + playerIdString + "' did not revive"));
			}
		}
	}
	public static class PatchesForRPC
	{
		public static ManualLogSource mls;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	internal static class HUDManagerPatchForRPC
	{
		private static float lastRecievedAt = Time.time;

		private static string lastRecievedMessage = null;

		private static float messageWaitTime = 0.5f;

		[HarmonyPatch("AddPlayerChatMessageClientRpc")]
		[HarmonyPrefix]
		private static void addPlayerChatMessageClientRpcPatch(ref string chatMessage, ref int playerId)
		{
			string text = MessageCodeUtil.returnMessageNoSeperators(chatMessage);
			if (MessageCodeUtil.stringContainsMessageCode(chatMessage) && (Time.time - lastRecievedAt > messageWaitTime || text != lastRecievedMessage) && playerId != (int)GameNetworkManager.Instance.localPlayerController.playerClientId)
			{
				lastRecievedAt = Time.time;
				lastRecievedMessage = text;
				RpcMessageHandler.ReceiveRpcMessage(chatMessage, playerId);
			}
		}

		[HarmonyPatch("AddChatMessage")]
		[HarmonyPrefix]
		private static bool addChatMessagePatch(ref string chatMessage)
		{
			if (MessageCodeUtil.stringContainsMessageCode(chatMessage))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal static class StartOfRoundPatchForRPC
	{
		[HarmonyPatch("OnClientConnect")]
		[HarmonyPostfix]
		private static void patchOnClientConnect(StartOfRound __instance)
		{
			((MonoBehaviour)__instance).StartCoroutine(activateModForOthers(__instance));
		}

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void patchStart(StartOfRound __instance)
		{
			if (((NetworkBehaviour)__instance).IsHost)
			{
				GlobalVariables.ModActivated = true;
			}
		}

		[HarmonyPatch("OnLocalDisconnect")]
		[HarmonyPostfix]
		private static void patchOnLocalDisconnect(StartOfRound __instance)
		{
			GlobalVariables.ModActivated = false;
		}

		private static IEnumerator activateModForOthers(StartOfRound __instance)
		{
			yield return (object)new WaitForSeconds(3f);
			if (((NetworkBehaviour)__instance).IsHost)
			{
				GlobalVariables.ModActivated = true;
				RpcMessage rpcMessage = new RpcMessage(MessageTasks.ModActivated, PatchesForRPC.mls.SourceName, (int)__instance.localPlayerController.playerClientId, MessageCodes.Request);
				RpcMessageHandler.SendRpcMessage(rpcMessage);
			}
		}
	}
	public enum MessageCodes
	{
		Request,
		Response
	}
	public static class MessageCodeUtil
	{
		public static string GetCode(MessageCodes code)
		{
			return code switch
			{
				MessageCodes.Request => ":rpcRequest:", 
				MessageCodes.Response => ":rpcResponse:", 
				_ => ":Error:", 
			};
		}

		public static bool stringContainsMessageCode(string givenString)
		{
			if (string.IsNullOrEmpty(givenString))
			{
				return false;
			}
			return givenString.Contains(GetCode(MessageCodes.Request)) || givenString.Contains(GetCode(MessageCodes.Response));
		}

		public static string returnMessageWithoutCode(string message)
		{
			if (stringContainsMessageCode(message))
			{
				message = message.Replace(GetCode(MessageCodes.Request), string.Empty);
				message = message.Replace(GetCode(MessageCodes.Response), string.Empty);
			}
			return message;
		}

		public static string returnMessageNoSeperators(string message)
		{
			if (stringContainsMessageCode(message))
			{
				return new string(message.Where((char c) => c != ':').ToArray());
			}
			return message;
		}
	}
	public enum MessageTasks
	{
		ModActivated,
		RevivePlayer,
		TurnOffGhostMode,
		ErrorNoTask
	}
	public static class MessageTaskUtil
	{
		public static string GetCode(MessageTasks code)
		{
			return code switch
			{
				MessageTasks.ModActivated => ":ModActivated:", 
				MessageTasks.RevivePlayer => ":RevivePlayer:", 
				MessageTasks.TurnOffGhostMode => ":TurnOffGhostMode:", 
				MessageTasks.ErrorNoTask => ":Error:", 
				_ => ":Error:", 
			};
		}

		public static string getMessageWithoutTask(string message)
		{
			foreach (MessageTasks value in Enum.GetValues(typeof(MessageTasks)))
			{
				string code2 = GetCode(value);
				message = message.Replace(code2, "");
			}
			return message.Trim();
		}

		public static MessageTasks getMessageTask(string givenString)
		{
			if (givenString.Contains(GetCode(MessageTasks.ModActivated)))
			{
				return MessageTasks.ModActivated;
			}
			if (givenString.Contains(GetCode(MessageTasks.RevivePlayer)))
			{
				return MessageTasks.RevivePlayer;
			}
			if (givenString.Contains(GetCode(MessageTasks.TurnOffGhostMode)))
			{
				return MessageTasks.TurnOffGhostMode;
			}
			return MessageTasks.ErrorNoTask;
		}
	}
	public class RpcMessage
	{
		public MessageTasks Task { get; set; }

		public string Message { get; set; }

		public int FromUser { get; set; }

		public MessageCodes MessageCode { get; set; }

		public RpcMessage(MessageTasks task, string message, int user, MessageCodes code)
		{
			Task = task;
			Message = message;
			FromUser = user;
			MessageCode = code;
		}

		public string getMessageWithCode()
		{
			return MessageCodeUtil.GetCode(MessageCode) + MessageTaskUtil.GetCode(Task) + Message;
		}
	}
	public static class RpcMessageHandler
	{
		private static ManualLogSource mls;

		private static RpcMessage lastSentMessage = null;

		private static float lastSentTime = Time.time;

		private static float messageWaitTime = 0.5f;

		public static void SetLogSource(ManualLogSource logSource)
		{
			mls = logSource;
		}

		public static void SendRpcMessage(RpcMessage message)
		{
			if (Time.time - lastSentTime > messageWaitTime || lastSentMessage != message)
			{
				mls.LogMessage((object)$"Sending rpc message: {message.getMessageWithCode()}, user:{message.FromUser}");
				lastSentTime = Time.time;
				lastSentMessage = message;
				HUDManager instance = HUDManager.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					MethodInfo method = typeof(HUDManager).GetMethod("AddPlayerChatMessageServerRpc", BindingFlags.Instance | BindingFlags.NonPublic);
					if (method != null)
					{
						object[] parameters = new object[2]
						{
							message.getMessageWithCode(),
							message.FromUser
						};
						method.Invoke(instance, parameters);
					}
					else
					{
						mls.LogError((object)"AddPlayerChatMessageServerRpc method not found in HUDManager class.");
					}
				}
				else
				{
					mls.LogError((object)"HUDManager.Instance is null.");
				}
			}
			else
			{
				mls.LogError((object)("didnt' send message as it was too soon and was the same message as last message " + message.getMessageWithCode()));
			}
		}

		public static void ReceiveRpcMessage(string message, int user)
		{
			mls.LogMessage((object)$"recieved message: {message}, user:{user}");
			if (user != (int)StartOfRound.Instance.localPlayerController.playerClientId)
			{
				string text = MessageCodeUtil.returnMessageWithoutCode(message);
				if (message.Contains(MessageCodeUtil.GetCode(MessageCodes.Request)))
				{
					MessageTasks messageTask = MessageTaskUtil.getMessageTask(text);
					string messageWithoutTask = MessageTaskUtil.getMessageWithoutTask(text);
					SendRpcResponse(messageTask, messageWithoutTask);
					handleTask(messageTask, messageWithoutTask);
				}
				else if (message.Contains(MessageCodeUtil.GetCode(MessageCodes.Response)))
				{
					ResponseHandler.RecievedResponse(MessageTaskUtil.getMessageTask(text));
				}
			}
		}

		public static void SendRpcResponse(MessageTasks task, string message)
		{
			try
			{
				RpcMessage message2 = new RpcMessage(task, message, (int)StartOfRound.Instance.localPlayerController.playerClientId, MessageCodes.Response);
				SendRpcMessage(message2);
			}
			catch (Exception arg)
			{
				mls.LogError((object)$"failed to send response message: {arg}");
			}
		}

		private static void handleTask(MessageTasks task, string message)
		{
			try
			{
				switch (task)
				{
				case MessageTasks.ModActivated:
					CompleteRecievedTasks.ModActivated(message);
					break;
				case MessageTasks.RevivePlayer:
					CompleteRecievedTasks.RevivePlayer(message);
					break;
				case MessageTasks.ErrorNoTask:
					mls.LogError((object)"got an error task");
					break;
				case MessageTasks.TurnOffGhostMode:
					break;
				}
			}
			catch (Exception arg)
			{
				mls.LogError((object)$"failed handlign rpc task: {arg}, task:{task}, message:{message}");
			}
		}
	}
}