Decompiled source of RespawnSystem v1.9.4

RespawnMod_M4GMaR.dll

Decompiled 2 weeks 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.Bootstrap;
using HarmonyLib;
using Mirror;
using MoveClasses;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("RespawnMod_M4GMaR")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RespawnMod_M4GMaR")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("fc922182-bb62-4b0d-8de5-46794294d7cf")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("com.yourname.respawnmod", "Respawn Mod", "1.9.4")]
public class RespawnMod : BaseUnityPlugin
{
	[HarmonyPatch(typeof(StaminaManager), "UpdateStaminaJobItems")]
	private class Patch_StaminaManager_UpdateStaminaJobItems
	{
		private static void Prefix(StaminaManager __instance)
		{
			try
			{
				for (int num = __instance.staminaItems.Count - 1; num >= 0; num--)
				{
					StaminaItem val = __instance.staminaItems[num];
					if (val == null || (Object)(object)val.playerHealth == (Object)null || (Object)(object)((Component)val.playerHealth).gameObject == (Object)null)
					{
						__instance.staminaItems.RemoveAt(num);
					}
				}
			}
			catch (Exception arg)
			{
				Debug.LogWarning((object)$"[RespawnMod-DEBUG] Error cleaning staminaItems: {arg}");
			}
		}
	}

	[HarmonyPatch(typeof(LargeBladeTrigger), "FixedUpdate")]
	private class Patch_LargeBladeTrigger_FixedUpdate
	{
		private static readonly FieldInfo fiWeapon = AccessTools.Field(typeof(LargeBladeTrigger), "weapon");

		private static readonly FieldInfo fiDisableLocalLogic = AccessTools.Field(typeof(LargeBladeTrigger), "disableLocalLogic");

		private static readonly FieldInfo fiPenetratingColliders = AccessTools.Field(typeof(LargeBladeTrigger), "penetratingColliders");

		private static readonly FieldInfo fiPenetratingGameObjects = AccessTools.Field(typeof(LargeBladeTrigger), "penetratingGameObjects");

		private static bool Prefix(LargeBladeTrigger __instance)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			try
			{
				if (fiWeapon == null || fiDisableLocalLogic == null || fiPenetratingColliders == null || fiPenetratingGameObjects == null)
				{
					return true;
				}
				if ((bool)fiDisableLocalLogic.GetValue(__instance))
				{
					return false;
				}
				Weapon val = (Weapon)fiWeapon.GetValue(__instance);
				if ((Object)(object)val != (Object)null)
				{
					return true;
				}
				if ((Object)(object)((Component)__instance).transform != (Object)null && (Object)(object)((Component)__instance).transform.parent != (Object)null)
				{
					Weapon component = ((Component)((Component)__instance).transform.parent).GetComponent<Weapon>();
					if ((Object)(object)component != (Object)null)
					{
						fiWeapon.SetValue(__instance, component);
						return true;
					}
				}
				IList<Collider> list = fiPenetratingColliders.GetValue(__instance) as IList<Collider>;
				IList<GameObject> list2 = fiPenetratingGameObjects.GetValue(__instance) as IList<GameObject>;
				try
				{
					list?.Clear();
				}
				catch
				{
				}
				try
				{
					list2?.Clear();
				}
				catch
				{
				}
				fiDisableLocalLogic.SetValue(__instance, true);
				Debug.LogWarning((object)"[RespawnMod] LargeBladeTrigger: weapon missing — disabled trigger logic to avoid NRE.");
				return false;
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[RespawnMod] Patch_LargeBladeTrigger_FixedUpdate exception: " + ex));
				return true;
			}
		}
	}

	[HarmonyPatch(typeof(Weapon), "IgnoreCollision")]
	private class Patch_Weapon_IgnoreCollision
	{
		private static bool Prefix(Weapon __instance, Collider[] colliders, bool ignore = true)
		{
			try
			{
				if (colliders == null)
				{
					return false;
				}
				List<Collider> bladeColliders = __instance.bladeColliders;
				if (bladeColliders == null || bladeColliders.Count == 0)
				{
					return false;
				}
				foreach (Collider val in colliders)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					foreach (Collider item in bladeColliders)
					{
						if (!((Object)(object)item == (Object)null))
						{
							try
							{
								Physics.IgnoreCollision(val, item, ignore);
							}
							catch (Exception)
							{
							}
						}
					}
				}
			}
			catch (Exception ex2)
			{
				Debug.LogWarning((object)("[RespawnMod] Patch_Weapon_IgnoreCollision exception: " + ex2));
			}
			return false;
		}
	}

	public static GameObject leftHandWeapon = null;

	public static GameObject rightHandWeapon = null;

	private static readonly Dictionary<PlayerHealth, float> RespawningPlayers = new Dictionary<PlayerHealth, float>();

	private static readonly Dictionary<Rigidbody, float> OrphanedObjects = new Dictionary<Rigidbody, float>();

	private Coroutine _cleanerCoroutine;

	private Coroutine PositionSyncCoroutine;

	public static RespawnMod Instance { get; private set; }

	private void Awake()
	{
		((Object)Chainloader.ManagerObject).hideFlags = (HideFlags)61;
		Instance = this;
		Harmony.CreateAndPatchAll(typeof(RespawnMod), (string)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"AWAKE: Hooking into SceneManager.sceneLoaded");
		SceneManager.sceneLoaded += OnSceneLoaded;
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)("SCENE LOADED: " + ((Scene)(ref scene)).name));
		RespawningPlayers.Clear();
		if (_cleanerCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(_cleanerCoroutine);
			_cleanerCoroutine = null;
		}
		if (PositionSyncCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(PositionSyncCoroutine);
			PositionSyncCoroutine = null;
		}
		if (NetworkServer.active)
		{
			_cleanerCoroutine = ((MonoBehaviour)this).StartCoroutine(Cleaner());
		}
	}

	private static void CleanRespawningPlayers()
	{
		float time = Time.time;
		List<PlayerHealth> list = new List<PlayerHealth>();
		foreach (KeyValuePair<PlayerHealth, float> respawningPlayer in RespawningPlayers)
		{
			PlayerHealth key = respawningPlayer.Key;
			float value = respawningPlayer.Value;
			if ((Object)(object)key == (Object)null || time - value > 10f)
			{
				list.Add(key);
			}
		}
		foreach (PlayerHealth item in list)
		{
			RespawningPlayers.Remove(item);
			if ((Object)(object)item != (Object)null)
			{
				item.Die((DeathReason)3);
			}
		}
	}

	private static IEnumerator TrackAndCleanOrphanedObjects()
	{
		float now = Time.time;
		Rigidbody[] rigidbodies = Object.FindObjectsOfType<Rigidbody>();
		Rigidbody[] array = rigidbodies;
		foreach (Rigidbody rb in array)
		{
			if (!((Object)(object)((Component)rb).GetComponentInParent<PlayerHealth>() != (Object)null))
			{
				if (!OrphanedObjects.ContainsKey(rb))
				{
					OrphanedObjects[rb] = now;
				}
				else if (now - OrphanedObjects[rb] > 30f)
				{
					yield return ((MonoBehaviour)Instance).StartCoroutine(SafeDestroyGameObject(((Component)rb).gameObject));
					OrphanedObjects.Remove(rb);
				}
			}
			else if (OrphanedObjects.ContainsKey(rb))
			{
				OrphanedObjects.Remove(rb);
			}
		}
		List<Rigidbody> nullKeys = new List<Rigidbody>();
		foreach (KeyValuePair<Rigidbody, float> kvp in OrphanedObjects)
		{
			if ((Object)(object)kvp.Key == (Object)null)
			{
				nullKeys.Add(kvp.Key);
			}
		}
		foreach (Rigidbody key in nullKeys)
		{
			OrphanedObjects.Remove(key);
		}
	}

	private static IEnumerator Cleaner()
	{
		while (true)
		{
			yield return (object)new WaitForSeconds(5f);
			CleanRespawningPlayers();
			((MonoBehaviour)Instance).StartCoroutine(TrackAndCleanOrphanedObjects());
			if ((Object)(object)StaminaManager.singleton != (Object)null)
			{
				StaminaManager.singleton.HandleExistingJob();
				StaminaManager.singleton.staminaItems.RemoveAll((StaminaItem si) => si == null);
				typeof(StaminaManager).GetMethod("ScheduleNextJob", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(StaminaManager.singleton, null);
			}
		}
	}

	[HarmonyPatch(typeof(PlayerHealth), "Die")]
	[HarmonyPrefix]
	private static bool PreventOriginalDeath(PlayerHealth __instance)
	{
		if (!NetworkServer.active)
		{
			return false;
		}
		if (RespawningPlayers.ContainsKey(__instance))
		{
			return false;
		}
		Debug.Log((object)("[RespawnMod-DEBUG] Player " + ((__instance != null) ? ((Object)__instance).name : null) + " triggered Die()"));
		RespawningPlayers[__instance] = Time.time;
		((MonoBehaviour)Instance).StartCoroutine(SimulateDeathAndResurrect(__instance));
		return false;
	}

	private static IEnumerator SimulateDeathAndResurrect(PlayerHealth player)
	{
		PlayerHealth obj = player;
		Debug.Log((object)("[RespawnMod-DEBUG] Simulating death for " + ((obj != null) ? ((Object)obj).name : null)));
		if ((Object)(object)player == (Object)null || !NetworkServer.active)
		{
			Debug.LogWarning((object)"[RespawnMod-DEBUG] Invalid player or server not active");
			RespawningPlayers.Remove(player);
			yield break;
		}
		try
		{
			SetAllJointStrengths(player, 0f);
			SetBallHolderJointStrength(player, 0f);
			player?.bleedableOrgans?.ForEach(delegate(WeaponDamageablePart organ)
			{
				organ.StopDestroyVisuals();
			});
		}
		catch (Exception ex2)
		{
			Exception ex = ex2;
			Debug.LogWarning((object)$"[RespawnMod-DEBUG] Error setting joint strengths: {ex}");
		}
		try
		{
			if (player.leftHand?.currentlyGrabbedItem != null)
			{
				Weapon weapon = player.leftHand.currentlyGrabbedItem.GetWeapon();
				leftHandWeapon = ((weapon != null) ? ((Component)weapon).gameObject : null);
			}
			if (player.rightHand?.currentlyGrabbedItem != null)
			{
				Weapon weapon2 = player.rightHand.currentlyGrabbedItem.GetWeapon();
				rightHandWeapon = ((weapon2 != null) ? ((Component)weapon2).gameObject : null);
			}
		}
		catch
		{
		}
		try
		{
			((MonoBehaviour)player).Invoke("HandleHandsOnDeath", 0.4f);
		}
		catch
		{
		}
		yield return (object)new WaitForSecondsRealtime(0.05f);
		float elapsed = 0f;
		while (elapsed < 5f && (Object)(object)player != (Object)null && (Object)(object)((Component)player).gameObject != (Object)null)
		{
			elapsed += Time.deltaTime;
			try
			{
				SetAllJointStrengths(player, 0f);
			}
			catch
			{
			}
			yield return null;
		}
		PlayerMultiplayerInputManager inputManager = FindInputManager(player);
		if ((Object)(object)StaminaManager.singleton != (Object)null)
		{
			StaminaManager.singleton.HandleExistingJob();
			StaminaManager.singleton.staminaItems.RemoveAll((StaminaItem si) => si == null || (Object)(object)si.playerHealth == (Object)(object)player);
			typeof(StaminaManager).GetMethod("ScheduleNextJob", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(StaminaManager.singleton, null);
		}
		try
		{
			((MonoBehaviour)player).Invoke("HandleHandsOnDeath", 0.4f);
		}
		catch
		{
		}
		yield return (object)new WaitForSeconds(0.41f);
		if ((Object)(object)inputManager != (Object)null)
		{
			try
			{
				((MonoBehaviour)player).Invoke("HandleHandsOnDeath", 0.1f);
			}
			catch
			{
			}
			yield return ((MonoBehaviour)Instance).StartCoroutine(SafeDestroyGameObject(leftHandWeapon));
			leftHandWeapon = null;
			try
			{
				((MonoBehaviour)player).Invoke("HandleHandsOnDeath", 0.1f);
			}
			catch
			{
			}
			yield return ((MonoBehaviour)Instance).StartCoroutine(SafeDestroyGameObject(rightHandWeapon));
			rightHandWeapon = null;
			try
			{
				((MonoBehaviour)player).Invoke("HandleHandsOnDeath", 0.1f);
			}
			catch
			{
			}
			RespawnMod instance = Instance;
			PlayerHealth obj9 = player;
			yield return ((MonoBehaviour)instance).StartCoroutine(SafeDestroyGameObject((obj9 != null) ? ((Component)obj9).gameObject : null));
			ResetInputManager(inputManager);
			yield return (object)new WaitForSecondsRealtime(0.4f);
			yield return ((MonoBehaviour)Instance).StartCoroutine(Instance.Resurrect(inputManager));
		}
		else
		{
			Debug.Log((object)"InputManager not found, destroying character");
			RespawnMod instance2 = Instance;
			PlayerHealth obj10 = player;
			yield return ((MonoBehaviour)instance2).StartCoroutine(SafeDestroyGameObject((obj10 != null) ? ((Component)obj10).gameObject : null));
		}
	}

	private static IEnumerator SafeDestroyGameObject(GameObject go)
	{
		if ((Object)(object)go == (Object)null)
		{
			yield break;
		}
		go.layer = 9;
		foreach (Transform item in go.transform)
		{
			Transform child = item;
			((Component)child).gameObject.layer = 9;
		}
		yield return (object)new WaitForFixedUpdate();
		Transform transform = go.transform;
		transform.position += new Vector3(128f, 128f, 128f);
		yield return (object)new WaitForSeconds(0.1f);
		try
		{
			NetworkIdentity nid = go.GetComponent<NetworkIdentity>();
			if ((Object)(object)nid != (Object)null && nid.netId != 0 && NetworkServer.spawned.ContainsKey(nid.netId))
			{
				NetworkServer.Destroy(go);
			}
			else
			{
				Object.Destroy((Object)(object)go);
			}
		}
		catch
		{
		}
	}

	public IEnumerator Resurrect(PlayerMultiplayerInputManager IM)
	{
		IM.moveSet = IM.multiplayerRoomPlayer.selectedMoveSet;
		IM.equippedEquipment = IM.multiplayerRoomPlayer.selectedEquipment.ToList();
		yield return (object)new WaitForSecondsRealtime(0.4f);
		IM.AttemptToCreatePlayerCharacter();
		yield return (object)new WaitForSecondsRealtime(0.2f);
		Type ftpType = AccessTools.TypeByName("FeelThePunch");
		if (!(ftpType != null))
		{
			yield break;
		}
		object instance = ftpType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
		if (instance != null)
		{
			MethodInfo method = ftpType.GetMethod("DelayedSetup", BindingFlags.Instance | BindingFlags.Public);
			if (method != null)
			{
				((MonoBehaviour)Instance).StartCoroutine((IEnumerator)method.Invoke(instance, null));
			}
		}
	}

	private static PlayerMultiplayerInputManager FindInputManager(PlayerHealth player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return null;
		}
		NetworkIdentity nid = ((Component)player).GetComponent<NetworkIdentity>();
		if ((Object)(object)nid == (Object)null)
		{
			return null;
		}
		return ((IEnumerable<PlayerMultiplayerInputManager>)Resources.FindObjectsOfTypeAll<PlayerMultiplayerInputManager>()).FirstOrDefault((Func<PlayerMultiplayerInputManager, bool>)delegate(PlayerMultiplayerInputManager mgr)
		{
			try
			{
				Traverse<uint> val = Traverse.Create((object)mgr).Field<uint>("playerHealthIdentity");
				return val != null && val.Value == nid.netId;
			}
			catch
			{
				return false;
			}
		});
	}

	private static void ResetInputManager(PlayerMultiplayerInputManager mgr)
	{
		if ((Object)(object)mgr == (Object)null)
		{
			return;
		}
		Debug.Log((object)"[RespawnMod-DEBUG] Resetting InputManager fields");
		try
		{
			Traverse val = Traverse.Create((object)mgr);
			val.Field("playerHealth").SetValue((object)null);
			val.Field("playerHealthInitialized").SetValue((object)false);
			val.Field("playerHealthIdentity").SetValue((object)0u);
			MultiplayerRoomPlayer multiplayerRoomPlayer = mgr.multiplayerRoomPlayer;
			if ((Object)(object)multiplayerRoomPlayer != (Object)null)
			{
				Traverse val2 = Traverse.Create((object)multiplayerRoomPlayer);
				try
				{
					val2.Field("joinedMidGame").SetValue((object)false);
					return;
				}
				catch
				{
					return;
				}
			}
		}
		catch (Exception arg)
		{
			Debug.LogWarning((object)$"[RespawnMod-DEBUG] Error resetting input manager: {arg}");
		}
	}

	private static void SetAllJointStrengths(PlayerHealth player, float strength)
	{
		JointStrength[] componentsInChildren = ((Component)player).GetComponentsInChildren<JointStrength>();
		foreach (JointStrength val in componentsInChildren)
		{
			try
			{
				val.SetStrengthPercent(strength);
			}
			catch
			{
			}
		}
	}

	private static void SetBallHolderJointStrength(PlayerHealth player, float strengthPercent)
	{
		//IL_0018: 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_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: 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)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)player.ballHolderjoint == (Object)null))
		{
			JointDrive val = default(JointDrive);
			JointDrive angularXDrive = player.ballHolderjoint.angularXDrive;
			((JointDrive)(ref val)).positionSpring = ((JointDrive)(ref angularXDrive)).positionSpring * (strengthPercent / 100f);
			angularXDrive = player.ballHolderjoint.angularXDrive;
			((JointDrive)(ref val)).positionDamper = ((JointDrive)(ref angularXDrive)).positionDamper * (strengthPercent / 100f);
			angularXDrive = player.ballHolderjoint.angularXDrive;
			((JointDrive)(ref val)).maximumForce = ((JointDrive)(ref angularXDrive)).maximumForce;
			JointDrive val2 = val;
			player.ballHolderjoint.angularXDrive = val2;
			player.ballHolderjoint.angularYZDrive = val2;
		}
	}

	[HarmonyPatch(typeof(MultiplayerRoomPlayer), "GetJoinedMidGame")]
	[HarmonyPrefix]
	private static bool ForceGetJoinedMidGameFalse(ref bool __result)
	{
		__result = false;
		return false;
	}

	[HarmonyPatch(typeof(PlayerHealth), "HandleDeath")]
	[HarmonyPrefix]
	private static bool PreventHandleDeath()
	{
		return false;
	}

	[HarmonyPatch(typeof(PlayerHealth), "HandleClientDeath")]
	[HarmonyPrefix]
	private static bool PreventClientDeath()
	{
		return false;
	}

	[HarmonyPatch(typeof(PlayerInputManager), "HandlePlayerDeath")]
	[HarmonyPrefix]
	private static bool PreventInputDisabling()
	{
		return false;
	}

	[HarmonyPatch(typeof(PlayerAnimator), "PlayerDied")]
	[HarmonyPrefix]
	private static bool PreventAnimatorDeathState()
	{
		return false;
	}
}