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;
}
}
}
}