Decompiled source of EnemyTestSpawner v1.1.0

EnemyTestSpawner.dll

Decompiled 15 hours 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.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using REPOLib.Modules;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("EnemyTestSpawner")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EnemyTestSpawner")]
[assembly: AssemblyTitle("EnemyTestSpawner")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 EnemyTestSpawner
{
	[BepInPlugin("themorningstar.enemytestspawner", "Enemy Test Spawner", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "themorningstar.enemytestspawner";

		internal static ManualLogSource Log;

		internal static ConfigFile Cfg;

		internal static ConfigEntry<bool> EnabledCfg;

		internal static ConfigEntry<string> KeyCfg;

		internal static ConfigEntry<string> EnemyCfg;

		internal static ConfigEntry<float> DistCfg;

		private static bool _dropdownBound;

		private void Awake()
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Cfg = ((BaseUnityPlugin)this).Config;
			EnabledCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", false, "Master switch for the debug enemy spawner. Leave FALSE for normal/shipped play.");
			KeyCfg = ((BaseUnityPlugin)this).Config.Bind<string>("General", "SpawnKey", "Insert", "Key that spawns the chosen enemy in front of you (any UnityEngine.KeyCode name, e.g. Insert, F2, Backslash, Keypad0).");
			DistCfg = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SpawnDistance", 3f, "How far in front of you the enemy spawns (metres).");
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Enemies), "RegisterEnemies", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					new Harmony("themorningstar.enemytestspawner").Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin).GetMethod("BindDropdown")), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else
				{
					BindPlainFallback();
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("EnemyTestSpawner: dropdown hook failed: " + ex));
				BindPlainFallback();
			}
			Log.LogInfo((object)"EnemyTestSpawner: loaded (disabled by default). Enable it + pick an enemy in REPOConfig; press the SpawnKey in a level.");
		}

		public static void BindDropdown()
		{
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			if (_dropdownBound)
			{
				return;
			}
			_dropdownBound = true;
			try
			{
				SortedSet<string> sortedSet = new SortedSet<string>(StringComparer.OrdinalIgnoreCase);
				try
				{
					foreach (EnemySetup allEnemy in Enemies.AllEnemies)
					{
						if ((Object)(object)allEnemy != (Object)null && !string.IsNullOrEmpty(((Object)allEnemy).name))
						{
							sortedSet.Add(((Object)allEnemy).name);
						}
					}
				}
				catch
				{
				}
				try
				{
					foreach (EnemySetup registeredEnemy in Enemies.RegisteredEnemies)
					{
						if ((Object)(object)registeredEnemy != (Object)null && !string.IsNullOrEmpty(((Object)registeredEnemy).name))
						{
							sortedSet.Add(((Object)registeredEnemy).name);
						}
					}
				}
				catch
				{
				}
				if (sortedSet.Count == 0)
				{
					BindPlainFallback();
					return;
				}
				string[] array = sortedSet.ToArray();
				string text = array.FirstOrDefault((string n) => n.IndexOf("Rolling Giant", StringComparison.OrdinalIgnoreCase) >= 0) ?? array[0];
				EnemyCfg = Cfg.Bind<string>("General", "Enemy", text, new ConfigDescription("Enemy to spawn (dropdown of registered enemies).", (AcceptableValueBase)(object)new AcceptableValueList<string>(array), Array.Empty<object>()));
				Log.LogInfo((object)$"EnemyTestSpawner: enemy dropdown ready ({array.Length} enemies).");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("EnemyTestSpawner: dropdown bind failed: " + ex));
				BindPlainFallback();
			}
		}

		private static void BindPlainFallback()
		{
			if (EnemyCfg == null)
			{
				EnemyCfg = Cfg.Bind<string>("General", "Enemy", "Rolling Giant", "Enemy to spawn (name or part of it). (Dropdown unavailable - REPOLib enemy list not found.)");
			}
		}

		private void Update()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (EnabledCfg == null || !EnabledCfg.Value)
			{
				return;
			}
			if (!Enum.TryParse<KeyCode>(KeyCfg.Value, ignoreCase: true, out KeyCode result))
			{
				result = (KeyCode)277;
			}
			if (!Input.GetKeyDown(result))
			{
				return;
			}
			try
			{
				Spawn();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("EnemyTestSpawner: spawn failed: " + ex));
			}
		}

		private void Spawn()
		{
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				Log.LogWarning((object)"EnemyTestSpawner: host/singleplayer only.");
				return;
			}
			EnemyDirector instance = EnemyDirector.instance;
			if ((Object)(object)instance == (Object)null)
			{
				Log.LogWarning((object)"EnemyTestSpawner: no EnemyDirector (are you in a level?).");
				return;
			}
			PlayerAvatar instance2 = PlayerAvatar.instance;
			if ((Object)(object)instance2 == (Object)null)
			{
				Log.LogWarning((object)"EnemyTestSpawner: no local player.");
				return;
			}
			string text = (EnemyCfg?.Value ?? "").Trim();
			EnemySetup val = FindSetup(instance, text);
			if ((Object)(object)val == (Object)null)
			{
				IEnumerable<string> values = from s in instance.enemiesDifficulty1.Concat(instance.enemiesDifficulty2).Concat(instance.enemiesDifficulty3)
					where (Object)(object)s != (Object)null
					select ((Object)s).name;
				Log.LogWarning((object)("EnemyTestSpawner: no enemy matching '" + text + "'. Available: " + string.Join(", ", values)));
				return;
			}
			Vector3 val2 = ((Component)instance2).transform.position + ((Component)instance2).transform.forward * DistCfg.Value + Vector3.up * 0.5f;
			Quaternion val3 = Quaternion.LookRotation(-((Component)instance2).transform.forward);
			bool flag = SemiFunc.IsMultiplayer();
			int num = 0;
			GameObject val4 = null;
			foreach (PrefabRef spawnObject in val.spawnObjects)
			{
				if (spawnObject == null)
				{
					continue;
				}
				GameObject val5 = null;
				try
				{
					val5 = (flag ? PhotonNetwork.InstantiateRoomObject(((PrefabRef<GameObject>)(object)spawnObject).ResourcePath, val2, val3, (byte)0, (object[])null) : (((Object)(object)((PrefabRef<GameObject>)(object)spawnObject).Prefab != (Object)null) ? Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)spawnObject).Prefab, val2, val3) : null));
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("EnemyTestSpawner: failed to spawn '" + ((PrefabRef<GameObject>)(object)spawnObject).PrefabName + "': " + ex.Message));
					continue;
				}
				if ((Object)(object)val5 != (Object)null)
				{
					num++;
					if ((Object)(object)val4 == (Object)null)
					{
						val4 = val5;
					}
				}
			}
			Log.LogInfo((object)$"EnemyTestSpawner: spawned '{((Object)val).name}' ({num} object(s)) at {val2}.");
			if ((Object)(object)val4 != (Object)null)
			{
				((MonoBehaviour)this).StartCoroutine(DumpComponents(val4));
			}
		}

		private IEnumerator DumpComponents(GameObject go)
		{
			for (int pass = 0; pass < 2; pass++)
			{
				yield return (object)new WaitForSeconds((pass == 0) ? 0.3f : 2.5f);
				if ((Object)(object)go == (Object)null)
				{
					Log.LogWarning((object)$"EnemyTestSpawner DUMP pass{pass}: enemy already destroyed.");
					break;
				}
				StringBuilder stringBuilder = new StringBuilder($"EnemyTestSpawner DUMP pass{pass} '{((Object)go).name}' rootActive={go.activeInHierarchy}:\n");
				int num = 0;
				MonoBehaviour[] componentsInChildren = go.GetComponentsInChildren<MonoBehaviour>(true);
				foreach (MonoBehaviour val in componentsInChildren)
				{
					if ((Object)(object)val == (Object)null)
					{
						num++;
						continue;
					}
					string name = ((object)val).GetType().Name;
					if (name.StartsWith("Enemy") || name == "PhotonView")
					{
						stringBuilder.Append($"   {((Object)((Component)val).gameObject).name}/{name} enabled={((Behaviour)val).enabled} goActive={((Component)val).gameObject.activeInHierarchy}\n");
					}
				}
				stringBuilder.Append($"   (+{num} MISSING-script component(s) in hierarchy)");
				Log.LogInfo((object)stringBuilder.ToString());
			}
		}

		private static EnemySetup FindSetup(EnemyDirector ed, string want)
		{
			List<EnemySetup>[] array = new List<EnemySetup>[3] { ed.enemiesDifficulty1, ed.enemiesDifficulty2, ed.enemiesDifficulty3 };
			List<EnemySetup>[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				foreach (EnemySetup item in array2[i])
				{
					if ((Object)(object)item != (Object)null && string.Equals(((Object)item).name, want, StringComparison.OrdinalIgnoreCase))
					{
						return item;
					}
				}
			}
			array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				foreach (EnemySetup item2 in array2[i])
				{
					if ((Object)(object)item2 != (Object)null && ((Object)item2).name != null && ((Object)item2).name.IndexOf(want, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return item2;
					}
				}
			}
			return null;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		internal IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}