Decompiled source of NoKillFloor v1.0.1

Mods/NoKillFloor.dll

Decompiled 7 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using HarmonyLib;
using Il2Cpp;
using Il2CppKeepsake;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using NoKillFloor;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Mod), "NoKillFloor", "1.0.1", "Isaac", null)]
[assembly: MelonGame(null, null)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("NoKillFloor")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("NoKillFloor")]
[assembly: AssemblyTitle("NoKillFloor")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 NoKillFloor
{
	public class Mod : MelonMod
	{
		private static MelonPreferences_Entry<bool> _enabled;

		private static MelonPreferences_Entry<bool> _verbose;

		private static MelonPreferences_Entry<string> _scenes;

		private static MelonPreferences_Entry<string> _blockTypes;

		private static Instance _log;

		private static readonly HashSet<string> _seen = new HashSet<string>();

		public override void OnInitializeMelon()
		{
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Expected O, but got Unknown
			_log = ((MelonBase)this).LoggerInstance;
			MelonPreferences_Category obj = MelonPreferences.CreateCategory("NoKillFloor");
			_enabled = obj.CreateEntry<bool>("Enabled", true, "Turn off the kill floor / damage floors", (string)null, false, false, (ValueValidator)null, (string)null);
			_scenes = obj.CreateEntry<string>("SceneNames", "lobby,hangar", "Comma-separated words; the mod is active while a loaded scene's name contains one of them. Use * for every scene.", (string)null, false, false, (ValueValidator)null, (string)null);
			_blockTypes = obj.CreateEntry<string>("BlockTriggerTypes", "", "Comma-separated trigger class names to skip entirely while active (filled in once the culprit is known)", (string)null, false, false, (ValueValidator)null, (string)null);
			_verbose = obj.CreateEntry<bool>("Debug", false, "Log every trigger/damage event the mod sees (for troubleshooting)", (string)null, false, false, (ValueValidator)null, (string)null);
			if (_verbose.Value)
			{
				try
				{
					int num = 0;
					HashSet<string> hashSet = new HashSet<string> { "OnTriggerEnter", "Handle_PlayerEntered", "OnOnPlayerEntered", "TriggerOnOnPlayerEntered", "OnOnShipEntered", "Handle_OnOverlapBegin" };
					HarmonyMethod val = new HarmonyMethod(typeof(Mod).GetMethod("TriggerPrefix", BindingFlags.Static | BindingFlags.NonPublic));
					Type[] types = typeof(PlayerController).Assembly.GetTypes();
					foreach (Type type in types)
					{
						if (type.IsAbstract || type.IsGenericType || type.Name.IndexOf("Trigger", StringComparison.OrdinalIgnoreCase) < 0)
						{
							continue;
						}
						MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
						foreach (MethodInfo methodInfo in methods)
						{
							if (hashSet.Contains(methodInfo.Name))
							{
								try
								{
									((MelonBase)this).HarmonyInstance.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
									num++;
								}
								catch
								{
								}
							}
						}
					}
					((MelonBase)this).LoggerInstance.Msg("Watching " + num + " trigger handlers");
				}
				catch (Exception ex)
				{
					((MelonBase)this).LoggerInstance.Error("trigger scan failed: " + ex.Message);
				}
			}
			try
			{
				MethodInfo methodInfo2 = (typeof(PlayerController).Assembly.GetType("Il2CppKeepsake.KillTrigger") ?? typeof(PlayerController).Assembly.GetType("Il2Cpp.KillTrigger"))?.GetMethod("TriggerOnOnPlayerEntered", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (methodInfo2 != null)
				{
					((MelonBase)this).HarmonyInstance.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(Mod).GetMethod("KillTriggerPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					((MelonBase)this).LoggerInstance.Msg("Patched KillTrigger");
				}
				else
				{
					((MelonBase)this).LoggerInstance.Warning("KillTrigger handler not found");
				}
			}
			catch (Exception ex2)
			{
				((MelonBase)this).LoggerInstance.Error("KillTrigger patch failed: " + ex2);
			}
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			((MelonBase)this).LoggerInstance.Msg("Scene loaded: " + sceneName + " | active scenes: " + SceneList());
		}

		private static string SceneList()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < SceneManager.sceneCount; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(", ");
				}
				Scene sceneAt = SceneManager.GetSceneAt(i);
				stringBuilder.Append(((Scene)(ref sceneAt)).name);
			}
			return stringBuilder.ToString();
		}

		private static bool InTargetScene()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			string value = _scenes.Value;
			if (string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			if (value.Trim() == "*")
			{
				return true;
			}
			string[] array = value.Split(',');
			for (int i = 0; i < SceneManager.sceneCount; i++)
			{
				Scene sceneAt = SceneManager.GetSceneAt(i);
				string name = ((Scene)(ref sceneAt)).name;
				string[] array2 = array;
				for (int j = 0; j < array2.Length; j++)
				{
					string text = array2[j].Trim();
					if (text.Length > 0 && name.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static string PathOf(Transform t)
		{
			string text = ((Object)t).name;
			int num = 0;
			while ((Object)(object)t.parent != (Object)null && num++ < 8)
			{
				t = t.parent;
				text = ((Object)t).name + "/" + text;
			}
			return text;
		}

		private static bool HurtPrefix(HurtTrigger __instance)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				bool flag = _enabled.Value && InTargetScene();
				if (_verbose.Value)
				{
					string item = "hurt:" + PathOf(((Component)__instance).transform) + ":" + flag;
					if (_seen.Add(item))
					{
						_log.Msg("HurtTrigger entered: " + PathOf(((Component)__instance).transform) + " damage=" + __instance.m_Damage + " type=" + ((object)__instance.m_DamageType/*cast due to .constrained prefix*/).ToString() + " defeatOnKill=" + __instance.m_DefeatPlayerOnKill + " scenes=[" + SceneList() + "] -> " + (flag ? "BLOCKED" : "allowed"));
					}
				}
				return !flag;
			}
			catch (Exception ex)
			{
				_log.Warning("hurt prefix: " + ex.Message);
				return true;
			}
		}

		private static bool DamagePrefix(DamageComponent __instance, ref DamageInfo damageInfo, ref bool __result)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)((Component)__instance).GetComponentInParent<PlayerController>() == (Object)null)
				{
					return true;
				}
				bool flag = _enabled.Value && InTargetScene();
				if (_verbose.Value)
				{
					string text = (((Object)(object)damageInfo.m_DamageSender != (Object)null) ? PathOf(damageInfo.m_DamageSender.transform) : "none");
					string item = "dmg:" + ((object)damageInfo.m_DamageType/*cast due to .constrained prefix*/).ToString() + ":" + text + ":" + flag;
					if (_seen.Add(item))
					{
						_log.Msg("Player damage: type=" + ((object)damageInfo.m_DamageType/*cast due to .constrained prefix*/).ToString() + " amount=" + damageInfo.m_Damage + " sender=" + text + " scenes=[" + SceneList() + "] -> " + (flag ? "BLOCKED" : "allowed"));
					}
				}
				if (flag)
				{
					__result = false;
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				_log.Warning("damage prefix: " + ex.Message);
				return true;
			}
		}

		private static bool HealthPrefix(HealthComponent_Base __instance, MethodBase __originalMethod, object[] __args)
		{
			try
			{
				if ((Object)(object)((Component)__instance).GetComponentInParent<PlayerController>() == (Object)null)
				{
					return true;
				}
				bool flag = _enabled.Value && InTargetScene();
				string name = __originalMethod.Name;
				bool flag2 = true;
				if ((name == "SetHealth" || name == "NetSetHealthServer") && __args != null && __args.Length != 0 && __args[0] is float num)
				{
					flag2 = num < __instance.Health;
				}
				if (name == "DoHealthModificationOnOthers" && __args != null && __args.Length != 0 && __args[0] is float num2)
				{
					flag2 = num2 < 0f;
				}
				if (!flag2)
				{
					return true;
				}
				if (_verbose.Value)
				{
					string item = "hp:" + name + ":" + flag;
					if (_seen.Add(item))
					{
						_log.Msg("Player health change via " + name + " args=" + ((__args == null) ? "" : string.Join(",", __args)) + " health=" + __instance.Health + " scenes=[" + SceneList() + "] -> " + (flag ? "BLOCKED" : "allowed"));
					}
				}
				return !flag;
			}
			catch (Exception ex)
			{
				_log.Warning("health prefix: " + ex.Message);
				return true;
			}
		}

		private static bool TriggerPrefix(object __instance, MethodBase __originalMethod)
		{
			try
			{
				Component val = (Component)((__instance is Component) ? __instance : null);
				string name = __originalMethod.DeclaringType.Name;
				bool num = _enabled.Value && InTargetScene();
				bool flag = false;
				if (num && !string.IsNullOrWhiteSpace(_blockTypes.Value))
				{
					string[] array = _blockTypes.Value.Split(',');
					for (int i = 0; i < array.Length; i++)
					{
						if (array[i].Trim().Equals(name, StringComparison.OrdinalIgnoreCase))
						{
							flag = true;
						}
					}
				}
				if (_verbose.Value && InTargetScene())
				{
					string text = (((Object)(object)val != (Object)null) ? PathOf(val.transform) : "?");
					string item = "trg:" + name + ":" + text;
					if (_seen.Add(item))
					{
						_log.Msg("Trigger fired: " + name + "." + __originalMethod.Name + " at " + text + (flag ? " -> BLOCKED" : ""));
					}
				}
				return !flag;
			}
			catch
			{
				return true;
			}
		}

		private static bool KillTriggerPrefix()
		{
			try
			{
				return !_enabled.Value || !InTargetScene();
			}
			catch
			{
				return true;
			}
		}

		private static bool KillPrefix()
		{
			try
			{
				bool flag = _enabled.Value && InTargetScene();
				if (_verbose.Value)
				{
					_log.Msg("KillLocalPlayer called; scenes=[" + SceneList() + "] -> " + (flag ? "BLOCKED" : "allowed"));
				}
				return !flag;
			}
			catch (Exception ex)
			{
				_log.Warning("kill prefix: " + ex.Message);
				return true;
			}
		}
	}
}