Decompiled source of LethalLibPrefabGuard v1.1.0

LethalLibPrefabGuard.dll

Decompiled 3 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("LethalLibPrefabGuard")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LethalLibPrefabGuard")]
[assembly: AssemblyTitle("LethalLibPrefabGuard")]
[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 LethalLibPrefabGuard
{
	[BepInPlugin("Harvy.LethalLibPrefabGuard", "LethalLib Prefab Guard", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class PrefabGuardPlugin : BaseUnityPlugin
	{
		public const string Guid = "Harvy.LethalLibPrefabGuard";

		internal static PrefabGuardPlugin Instance;

		private static Hook _startHook;

		private void Awake()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			Instance = this;
			MethodInfo method = typeof(StartOfRound).GetMethod("Start", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"StartOfRound.Start not found; guard inactive.");
				return;
			}
			_startHook = new Hook((MethodBase)method, typeof(PrefabGuardPlugin).GetMethod("StartOfRoundStartHook", BindingFlags.Static | BindingFlags.NonPublic));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Prefab guard hook installed around StartOfRound.Start (outside LethalLib's).");
		}

		private static void StartOfRoundStartHook(Action<StartOfRound> orig, StartOfRound self)
		{
			try
			{
				CleanLists(self);
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)Instance).Logger.LogWarning((object)$"Guard cleanup failed (continuing anyway): {arg}");
			}
			orig(self);
		}

		private static void CleanLists(StartOfRound self)
		{
			ReportBrokenRegistrations();
			Type type = AccessTools.TypeByName("LethalLib.Modules.Utilities");
			if (type != null && AccessTools.Field(type, "prefabsToFix")?.GetValue(null) is List<GameObject> list)
			{
				int num = list.RemoveAll((GameObject go) => (Object)(object)go == (Object)null);
				if (num > 0)
				{
					((BaseUnityPlugin)Instance).Logger.LogWarning((object)$"Removed {num} null prefab(s) from LethalLib's fix list — some mod registered a null prefab; without this guard the landing sequence would soft-lock.");
				}
			}
			if (!((Object)(object)self.allItemsList != (Object)null))
			{
				return;
			}
			IList itemsList = self.allItemsList.itemsList;
			if (itemsList == null)
			{
				return;
			}
			int num2 = 0;
			for (int num3 = itemsList.Count - 1; num3 >= 0; num3--)
			{
				object? obj = itemsList[num3];
				Object val = (Object)((obj is Object) ? obj : null);
				if (val == null || val == (Object)null)
				{
					itemsList.RemoveAt(num3);
					num2++;
				}
			}
			if (num2 > 0)
			{
				((BaseUnityPlugin)Instance).Logger.LogWarning((object)$"Removed {num2} null entry(ies) from StartOfRound.allItemsList — a mod registered a broken item.");
			}
		}

		private static void ReportBrokenRegistrations()
		{
			Type type = AccessTools.TypeByName("LethalLib.Modules.Items");
			if (type != null)
			{
				string[] array = new string[3] { "scrapItems", "shopItems", "plainItems" };
				foreach (string text in array)
				{
					if (!(AccessTools.Field(type, text)?.GetValue(null) is IEnumerable enumerable))
					{
						continue;
					}
					foreach (object item in enumerable)
					{
						if (item != null)
						{
							Type type2 = item.GetType();
							string text2 = (AccessTools.Field(type2, "modName")?.GetValue(item) as string) ?? "Unknown";
							object? obj = AccessTools.Field(type2, "item")?.GetValue(item);
							Item val = (Item)((obj is Item) ? obj : null);
							if (val == null || (Object)(object)val == (Object)null)
							{
								((BaseUnityPlugin)Instance).Logger.LogWarning((object)("CULPRIT: '" + text2 + "' registered a null Item in Items." + text + "."));
							}
							else if ((Object)(object)val.spawnPrefab == (Object)null)
							{
								((BaseUnityPlugin)Instance).Logger.LogWarning((object)("CULPRIT: '" + text2 + "' registered item '" + val.itemName + "' with a NULL spawnPrefab in Items." + text + "."));
							}
						}
					}
				}
			}
			Type type3 = AccessTools.TypeByName("LethalLib.Modules.Enemies");
			if (!(type3 != null) || !(AccessTools.Field(type3, "spawnableEnemies")?.GetValue(null) is IEnumerable enumerable2))
			{
				return;
			}
			foreach (object item2 in enumerable2)
			{
				if (item2 != null)
				{
					Type type4 = item2.GetType();
					string text3 = (AccessTools.Field(type4, "modName")?.GetValue(item2) as string) ?? "Unknown";
					object? obj2 = AccessTools.Field(type4, "enemy")?.GetValue(item2);
					EnemyType val2 = (EnemyType)((obj2 is EnemyType) ? obj2 : null);
					if (val2 == null || (Object)(object)val2 == (Object)null)
					{
						((BaseUnityPlugin)Instance).Logger.LogWarning((object)("CULPRIT: '" + text3 + "' registered a null EnemyType in Enemies.spawnableEnemies."));
					}
					else if ((Object)(object)val2.enemyPrefab == (Object)null)
					{
						((BaseUnityPlugin)Instance).Logger.LogWarning((object)("CULPRIT: '" + text3 + "' registered enemy '" + val2.enemyName + "' with a NULL enemyPrefab."));
					}
				}
			}
		}
	}
}