Decompiled source of MalfunctioningDoors v1.12.0

MalfunctioningDoors.dll

Decompiled 3 months ago
#define DEBUG
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DoorBreach;
using DoorBreach.Functional;
using GameNetcodeStuff;
using HarmonyLib;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using MalfunctioningDoors.Dependencies;
using MalfunctioningDoors.Functional;
using MalfunctioningDoors.Malfunctions;
using MalfunctioningDoors.Malfunctions.Impl;
using MalfunctioningDoors.Patches;
using Microsoft.CodeAnalysis;
using TestAccount666.MalfunctioningDoors.NetcodePatcher;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("TestAccount666.MalfunctioningDoors")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Who needs working doors anyway?")]
[assembly: AssemblyFileVersion("1.12.0.0")]
[assembly: AssemblyInformationalVersion("1.12.0+33af4244669c8a9d8e515335ef0d6e9bcea10fc8")]
[assembly: AssemblyProduct("MalfunctioningDoors")]
[assembly: AssemblyTitle("TestAccount666.MalfunctioningDoors")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.12.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 MalfunctioningDoors
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency("TestAccount666.DoorBreach", "1.1.0")]
	[BepInPlugin("TestAccount666.MalfunctioningDoors", "MalfunctioningDoors", "1.12.0")]
	public class MalfunctioningDoors : BaseUnityPlugin
	{
		private const int GHOST_HAND_SOUNDS_SIZE = 3;

		internal static Object ghostHandPrefab = null;

		internal static readonly AudioClip[] GhostHandSfxList = (AudioClip[])(object)new AudioClip[3];

		public static MalfunctioningDoors Instance { get; private set; } = null;


		internal static ManualLogSource Logger { get; private set; } = null;


		internal static Harmony? Harmony { get; set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			if (DependencyChecker.IsLobbyCompatibilityInstalled())
			{
				Logger.LogInfo((object)"Found LobbyCompatibility Mod, initializing support :)");
				LobbyCompatibilitySupport.Initialize();
			}
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			Debug.Assert(directoryName != null, "modDirectory != null");
			AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(directoryName, "ghosthand"));
			ghostHandPrefab = val.LoadAsset("ghosthand");
			Patch();
			DoorLockPatch.InitializeConfig(((BaseUnityPlugin)this).Config);
			MalfunctionalDoor.InitializeConfig(((BaseUnityPlugin)this).Config);
			FetchMalfunctions();
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				try
				{
					MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
					MethodInfo[] array2 = methods;
					foreach (MethodInfo methodInfo in array2)
					{
						object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
						if (customAttributes.Length != 0)
						{
							methodInfo.Invoke(null, null);
						}
					}
				}
				catch (FileNotFoundException)
				{
				}
			}
			((MonoBehaviour)this).StartCoroutine(LoadAudioClips());
			Logger.LogInfo((object)"TestAccount666.MalfunctioningDoors v1.12.0 has loaded!");
		}

		internal static void Patch()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony = new Harmony("TestAccount666.MalfunctioningDoors");
			}
			Logger.LogDebug((object)"Patching...");
			Harmony.PatchAll(typeof(DoorLockPatch));
			Harmony.PatchAll(typeof(RoundManagerPatch));
			Logger.LogDebug((object)"Finished patching!");
		}

		internal static void Unpatch()
		{
			Logger.LogDebug((object)"Unpatching...");
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Logger.LogDebug((object)"Finished unpatching!");
		}

		private static void FetchMalfunctions()
		{
			MalfunctionGenerator.MalfunctionDictionary.Clear();
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			IEnumerable<Type> enumerable = types.Where(Predicate);
			foreach (Type item in enumerable)
			{
				MalfunctionAttribute malfunctionAttribute = (MalfunctionAttribute)item.GetCustomAttribute(typeof(MalfunctionAttribute), inherit: false);
				int value = malfunctionAttribute.weight;
				MethodInfo method = item.GetMethod("OverrideWeight", BindingFlags.Static | BindingFlags.Public);
				if ((object)method != null)
				{
					value = (int)method.Invoke(null, new object[1] { ((BaseUnityPlugin)Instance).Config });
				}
				item.GetMethod("InitializeConfig", BindingFlags.Static | BindingFlags.Public)?.Invoke(null, new object[1] { ((BaseUnityPlugin)Instance).Config });
				MalfunctionGenerator.MalfunctionDictionary.Add(item, value);
			}
		}

		private static bool Predicate(ICustomAttributeProvider type)
		{
			return type.GetCustomAttributes(typeof(MalfunctionAttribute), inherit: false).Length != 0;
		}

		private static IEnumerator LoadAudioClips()
		{
			string assemblyDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			Logger.LogInfo((object)"Loading Sounds...");
			Debug.Assert(assemblyDirectory != null, "assemblyDirectory != null");
			string audioPath2 = Path.Combine(assemblyDirectory, "sounds");
			audioPath2 = (Directory.Exists(audioPath2) ? audioPath2 : Path.Combine(assemblyDirectory));
			LoadGhostHandAudioClips(audioPath2);
			yield break;
		}

		private static void LoadGhostHandAudioClips(string audioPath)
		{
			Logger.LogInfo((object)"Loading Ghost Hand Sounds...");
			string text = Path.Combine(audioPath, "GhostHandSounds");
			text = (Directory.Exists(text) ? text : Path.Combine(audioPath));
			for (int i = 1; i <= 3; i++)
			{
				int num = i - 1;
				AudioClip val = LoadAudioClipFromFile(new Uri(Path.Combine(text, $"GhostHand{i}.wav")), $"GhostHand{i}");
				if (val == null)
				{
					Logger.LogInfo((object)$"Failed to load clip 'GhostHand{i}'!");
					continue;
				}
				GhostHandSfxList[num] = val;
				Logger.LogInfo((object)("Loaded clip '" + ((Object)val).name + "'!"));
			}
		}

		private static AudioClip? LoadAudioClipFromFile(Uri filePath, string name)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(filePath, (AudioType)20);
			try
			{
				UnityWebRequestAsyncOperation val = audioClip.SendWebRequest();
				while (!((AsyncOperation)val).isDone)
				{
					Thread.Sleep(100);
				}
				if ((int)audioClip.result != 1)
				{
					Logger.LogError((object)("Failed to load AudioClip: " + audioClip.error));
					return null;
				}
				AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip);
				((Object)content).name = name;
				return content;
			}
			finally
			{
				((IDisposable)audioClip)?.Dispose();
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "TestAccount666.MalfunctioningDoors";

		public const string PLUGIN_NAME = "MalfunctioningDoors";

		public const string PLUGIN_VERSION = "1.12.0";
	}
}
namespace MalfunctioningDoors.Patches
{
	[HarmonyPatch(typeof(DoorLock))]
	public static class DoorLockPatch
	{
		public static Random syncedRandom = new Random();

		private static int _malfunctioningDoorChance = 30;

		public static void InitializeConfig(ConfigFile configFile)
		{
			_malfunctioningDoorChance = configFile.Bind<int>("1. General", "1. Malfunctional Door Chance", 30, "Defines the chance that a door can be malfunctional").Value;
		}

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		[HarmonyAfter(new string[] { "TestAccount666.DoorBreach" })]
		public static void AfterAwake(DoorLock __instance)
		{
			Type malfunctionalDoorType = typeof(DormantMalfunction);
			if (syncedRandom.Next(0, 100) < _malfunctioningDoorChance)
			{
				malfunctionalDoorType = MalfunctionGenerator.GenerateMalfunctionalDoor(syncedRandom);
			}
			AddMalfunction(__instance, malfunctionalDoorType);
		}

		[HarmonyPatch("UnlockDoorSyncWithServer")]
		[HarmonyPostfix]
		public static void AfterUnlockDoorSyncWithServer(DoorLock __instance)
		{
			MalfunctionalDoor component = ((Component)__instance).gameObject.GetComponent<MalfunctionalDoor>();
			if (component != null && component.ShouldExecute())
			{
				component.UseKey();
			}
		}

		internal static void AddMalfunction(DoorLock? doorLock, Type malfunctionalDoorType)
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			if (doorLock == null)
			{
				return;
			}
			if (!malfunctionalDoorType.IsSubclassOf(typeof(MalfunctionalDoor)))
			{
				throw new ArgumentException("Type '" + malfunctionalDoorType.FullName + "'");
			}
			MalfunctionalDoor malfunctionalDoor = (MalfunctionalDoor)(object)((Component)doorLock).gameObject.AddComponent(malfunctionalDoorType);
			((UnityEvent<PlayerControllerB>)(object)doorLock.doorTrigger.onInteract).AddListener((UnityAction<PlayerControllerB>)delegate(PlayerControllerB playerControllerB)
			{
				if (playerControllerB != null && malfunctionalDoor.ShouldExecute())
				{
					malfunctionalDoor.UseInteract(playerControllerB);
				}
			});
			InteractTrigger val = ((Component)doorLock).gameObject.AddComponent<InteractTrigger>();
			val.touchTrigger = true;
			val.interactable = true;
			val.onInteract = new InteractEvent();
			((UnityEvent<PlayerControllerB>)(object)val.onInteract).AddListener((UnityAction<PlayerControllerB>)delegate(PlayerControllerB playerControllerB)
			{
				if (playerControllerB != null && malfunctionalDoor.ShouldExecute())
				{
					malfunctionalDoor.TouchInteract(playerControllerB);
				}
			});
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	public static class RoundManagerPatch
	{
		[HarmonyPatch("GenerateNewLevelClientRpc")]
		[HarmonyPrefix]
		public static void BeforeGenerateNewLevelClientRpc(int randomSeed)
		{
			DoorLockPatch.syncedRandom = new Random(randomSeed);
		}
	}
}
namespace MalfunctioningDoors.Malfunctions
{
	public abstract class MalfunctionalDoor : MonoBehaviour
	{
		private static int _changeMalfunctionChance = 30;

		protected DoorLock? doorLock;

		private bool _destroy;

		private void Awake()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			EventHandler.doorBreach = (DoorBreachEvent)Delegate.Combine((Delegate?)(object)EventHandler.doorBreach, (Delegate?)new DoorBreachEvent(DestroyMalfunctions));
		}

		private void DestroyMalfunctions(DoorBreachEventArguments doorBreachEventArguments)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			EventHandler.doorBreach = (DoorBreachEvent)Delegate.Remove((Delegate?)(object)EventHandler.doorBreach, (Delegate?)new DoorBreachEvent(DestroyMalfunctions));
			if ((int)doorBreachEventArguments.doorBreachMode == 0)
			{
				return;
			}
			DoorLock? obj = doorLock;
			MalfunctionalDoor[] array = ((obj != null) ? ((Component)obj).GetComponents<MalfunctionalDoor>() : null);
			if (array == null)
			{
				array = Array.Empty<MalfunctionalDoor>();
			}
			MalfunctionalDoor[] array2 = array;
			foreach (MalfunctionalDoor malfunctionalDoor in array2)
			{
				if (malfunctionalDoor != null)
				{
					Object.Destroy((Object)(object)malfunctionalDoor);
				}
			}
		}

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(RollChangeMalfunctionChance());
		}

		private void OnDestroy()
		{
			_destroy = true;
		}

		protected bool IsDestroyed()
		{
			return _destroy;
		}

		public abstract void TouchInteract(PlayerControllerB playerControllerB);

		public abstract void UseInteract(PlayerControllerB playerControllerB);

		public static void InitializeConfig(ConfigFile configFile)
		{
			_changeMalfunctionChance = configFile.Bind<int>("1. General", "2. Malfunction Change Chance", 30, "Defines the chance, if a malfunction is changed").Value;
		}

		public abstract void UseKey();

		public abstract bool ShouldExecute();

		private IEnumerator RollChangeMalfunctionChance()
		{
			while (true)
			{
				yield return (object)new WaitForSeconds(60f);
				yield return (object)new WaitForEndOfFrame();
				if (_destroy)
				{
					yield break;
				}
				if (doorLock != null)
				{
					int chance = DoorLockPatch.syncedRandom.Next(0, 100);
					if (chance <= _changeMalfunctionChance)
					{
						break;
					}
				}
			}
			DoorLockPatch.AddMalfunction(malfunctionalDoorType: MalfunctionGenerator.GenerateMalfunctionalDoor(DoorLockPatch.syncedRandom), doorLock: doorLock);
			Object.Destroy((Object)(object)this);
		}
	}
	[AttributeUsage(AttributeTargets.Class)]
	public class MalfunctionAttribute : Attribute
	{
		internal readonly int weight;

		public MalfunctionAttribute(int weight = 1)
		{
			this.weight = weight;
			base..ctor();
		}
	}
	public class MalfunctionDictionary : Dictionary<Type, int>
	{
		public new void Add(Type key, int value)
		{
			if (!key.IsSubclassOf(typeof(MalfunctionalDoor)))
			{
				throw new InvalidOperationException("MalfunctionDictionary can only contain sub-types of " + typeof(MalfunctionalDoor).FullName + "!");
			}
			base.Add(key, value);
		}
	}
	public static class MalfunctionGenerator
	{
		public static readonly MalfunctionDictionary MalfunctionDictionary = new MalfunctionDictionary();

		public static Type GenerateMalfunctionalDoor(Random random)
		{
			int num = random.Next(1000, 9999);
			HashSet<KeyValuePair<Type, int>> hashSet = FisherYatesShuffle(MalfunctionDictionary, random).ToHashSet();
			while (num > 0)
			{
				foreach (KeyValuePair<Type, int> item in hashSet)
				{
					num -= item.Value;
					if (num > 0)
					{
						continue;
					}
					return item.Key;
				}
			}
			MalfunctioningDoors.Logger.LogError((object)"Couldn't find any malfunctional door type, falling back to CloseMalfunction as default!");
			return typeof(CloseMalfunction);
		}

		private static IEnumerable<KeyValuePair<TKey, TValue>> FisherYatesShuffle<TKey, TValue>(Dictionary<TKey, TValue> dictionary, Random random)
		{
			List<KeyValuePair<TKey, TValue>> list = dictionary.ToList();
			int num = list.Count;
			while (num > 1)
			{
				num--;
				int num2 = random.Next(num + 1);
				List<KeyValuePair<TKey, TValue>> list2 = list;
				int index = num2;
				int index2 = num;
				KeyValuePair<TKey, TValue> value = list[num];
				KeyValuePair<TKey, TValue> value2 = list[num2];
				list2[index] = value;
				list[index2] = value2;
			}
			return list;
		}
	}
}
namespace MalfunctioningDoors.Malfunctions.Impl
{
	[Malfunction(100)]
	public class CloseMalfunction : MalfunctionalDoor
	{
		private static int _lockChance = 30;

		private static int _lockWhenCloseChance = 80;

		private static int _openCloseAfterTwoSecondsChance = 40;

		private static int _malfunctionChance = 20;

		private Random _syncedRandom = null;

		private void Start()
		{
			doorLock = ((Component)this).GetComponent<DoorLock>();
			_syncedRandom = DoorLockPatch.syncedRandom;
		}

		public static int OverrideWeight(ConfigFile configFile)
		{
			return configFile.Bind<int>("2. Close Malfunction", "1. Malfunction Weight", 100, "Defines the weight of a malfunction. The higher, the more likely it is to appear").Value;
		}

		public new static void InitializeConfig(ConfigFile configFile)
		{
			_malfunctionChance = configFile.Bind<int>("2. Close Malfunction", "2. Malfunction Chance", 20, "Defines the chance, if a malfunction is executed").Value;
			_lockChance = configFile.Bind<int>("2. Close Malfunction", "3. Lock Chance", 30, "Defines the chance, if a door will be locked").Value;
			_lockWhenCloseChance = configFile.Bind<int>("2. Close Malfunction", "4. Lock When Close Chance", 80, "Defines the chance, if a door will be locked after closing (The 'Lock Chance' will be rolled first)").Value;
			_openCloseAfterTwoSecondsChance = configFile.Bind<int>("2. Close Malfunction", "5. Open Close After Two Seconds Chance", 40, "Defines the chance, if a door will open/close after two seconds after being opened/closed ('Malfunction Chance' will be rolled first)").Value;
		}

		public override void TouchInteract(PlayerControllerB playerControllerB)
		{
			if (doorLock == null || !doorLock.isDoorOpened || ((Component)doorLock).GetComponent<WaitingForDoorToBeClosed>() != null)
			{
				return;
			}
			int num = _syncedRandom.Next(0, 100);
			if (num >= _lockChance)
			{
				return;
			}
			int num2 = _syncedRandom.Next(0, 100);
			if (num2 < _lockWhenCloseChance)
			{
				WaitingForDoorToBeClosed waitingForDoorToBeClosed = ((Component)doorLock).gameObject.AddComponent<WaitingForDoorToBeClosed>();
				((MonoBehaviour)waitingForDoorToBeClosed).StartCoroutine(WaitingForDoorToBeClosed.WaitForDoorToBeClosed(doorLock));
				return;
			}
			MalfunctioningDoors.Logger.LogInfo((object)"Locking door <:)");
			doorLock.LockDoor(30f);
			DoorLocker component = ((Component)doorLock).gameObject.GetComponent<DoorLocker>();
			if (component == null)
			{
				MalfunctioningDoors.Logger.LogFatal((object)"No DoorLocker found?!");
			}
			else
			{
				component.LockDoorServerRpc();
			}
		}

		public override void UseInteract(PlayerControllerB playerControllerB)
		{
			PlayerControllerB playerControllerB2 = playerControllerB;
			if (doorLock == null)
			{
				return;
			}
			int num = _syncedRandom.Next(0, 100);
			DoorLocker doorLocker = ((Component)doorLock).gameObject.GetComponent<DoorLocker>();
			if (doorLocker == null)
			{
				MalfunctioningDoors.Logger.LogFatal((object)"No DoorLocker found?!");
				return;
			}
			bool open = !doorLock.isDoorOpened;
			if (num >= _openCloseAfterTwoSecondsChance)
			{
				doorLocker.SetDoorOpenServerRpc((int)playerControllerB2.playerClientId, open);
				return;
			}
			((MonoBehaviour)this).StartCoroutine(DelayedTask(2f, delegate
			{
				if (doorLock.isDoorOpened)
				{
					doorLocker.SetDoorOpenServerRpc((int)playerControllerB2.playerClientId, open);
				}
			}));
		}

		public override void UseKey()
		{
		}

		public override bool ShouldExecute()
		{
			return _syncedRandom.Next(0, 100) < _malfunctionChance && !IsDestroyed();
		}

		private static IEnumerator DelayedTask(float delay, Action action)
		{
			yield return (object)new WaitForSeconds(delay);
			yield return (object)new WaitForEndOfFrame();
			action();
		}
	}
	internal class WaitingForDoorToBeClosed : MonoBehaviour
	{
		private static bool _done;

		private void Update()
		{
			if (_done)
			{
				_done = false;
				Object.Destroy((Object)(object)this);
			}
		}

		internal static IEnumerator WaitForDoorToBeClosed(DoorLock doorLock)
		{
			MalfunctioningDoors.Logger.LogInfo((object)"Waiting for door to be closed :)");
			while (doorLock.isDoorOpened)
			{
				yield return (object)new WaitForSeconds(1f);
			}
			yield return (object)new WaitForEndOfFrame();
			MalfunctioningDoors.Logger.LogInfo((object)"Locking door <:)");
			doorLock.LockDoor(30f);
			DoorLocker doorLocker = ((Component)doorLock).gameObject.GetComponent<DoorLocker>();
			if (doorLocker == null)
			{
				MalfunctioningDoors.Logger.LogFatal((object)"No DoorLocker found?!");
				yield break;
			}
			doorLocker.LockDoorServerRpc();
			_done = true;
		}
	}
	[Malfunction(100)]
	public class DormantMalfunction : MalfunctionalDoor
	{
		public override void TouchInteract(PlayerControllerB playerControllerB)
		{
		}

		public override void UseInteract(PlayerControllerB playerControllerB)
		{
		}

		public override void UseKey()
		{
		}

		public override bool ShouldExecute()
		{
			return false;
		}
	}
	[Malfunction(65)]
	public class EatKeyMalfunction : MalfunctionalDoor
	{
		private static int _malfunctionChance = 65;

		private Random _syncedRandom = null;

		private void Start()
		{
			doorLock = ((Component)this).GetComponent<DoorLock>();
			_syncedRandom = DoorLockPatch.syncedRandom;
			((MonoBehaviour)this).StartCoroutine(LockDoorRoutine());
		}

		public static int OverrideWeight(ConfigFile configFile)
		{
			return configFile.Bind<int>("3. Eat Key Malfunction", "1. Malfunction Weight", 65, "Defines the weight of a malfunction. The higher, the more likely it is to appear").Value;
		}

		public new static void InitializeConfig(ConfigFile configFile)
		{
			_malfunctionChance = configFile.Bind<int>("3. Eat Key Malfunction", "2. Malfunction Chance", 65, "Defines the chance, if a malfunction is executed").Value;
		}

		public override void TouchInteract(PlayerControllerB playerControllerB)
		{
		}

		public override void UseInteract(PlayerControllerB playerControllerB)
		{
		}

		public override void UseKey()
		{
			((MonoBehaviour)this).StartCoroutine(LockDoorRoutine());
		}

		private IEnumerator LockDoorRoutine()
		{
			yield return (object)new WaitForEndOfFrame();
			yield return (object)new WaitUntil((Func<bool>)(() => doorLock != null));
			if (doorLock != null)
			{
				doorLock.LockDoor(30f);
				DoorLocker doorLocker = ((Component)doorLock).gameObject.GetComponent<DoorLocker>();
				if (doorLocker == null)
				{
					MalfunctioningDoors.Logger.LogFatal((object)"No DoorLocker found?!");
				}
				else
				{
					doorLocker.LockDoorServerRpc();
				}
			}
		}

		public override bool ShouldExecute()
		{
			return _syncedRandom.Next(0, 100) < _malfunctionChance && !IsDestroyed();
		}
	}
	[Malfunction(75)]
	public class GhostHandMalfunction : MalfunctionalDoor
	{
		private static int _malfunctionChance = 86;

		private Random _syncedRandom = null;

		private void Start()
		{
			doorLock = ((Component)this).GetComponent<DoorLock>();
			_syncedRandom = DoorLockPatch.syncedRandom;
		}

		public static int OverrideWeight(ConfigFile configFile)
		{
			return configFile.Bind<int>("4. Ghost Hand Malfunction", "1. Malfunction Weight", 75, "Defines the weight of a malfunction. The higher, the more likely it is to appear").Value;
		}

		public new static void InitializeConfig(ConfigFile configFile)
		{
			_malfunctionChance = configFile.Bind<int>("4. Ghost Hand Malfunction", "2. Malfunction Chance", 86, "Defines the chance, if a malfunction is executed").Value;
		}

		public override void TouchInteract(PlayerControllerB playerControllerB)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (doorLock != null && !doorLock.isDoorOpened)
			{
				DoorLocker component = ((Component)doorLock).gameObject.GetComponent<DoorLocker>();
				if (component == null)
				{
					MalfunctioningDoors.Logger.LogFatal((object)"No DoorLocker found?!");
					return;
				}
				component.SetDoorOpenServerRpc((int)playerControllerB.playerClientId, true);
				PlayGhostHandSound();
				CreateGhostHand((Component)(object)playerControllerB);
				playerControllerB.DamagePlayer(10, true, true, (CauseOfDeath)1, 1, false, playerControllerB.velocityLastFrame);
				Landmine.SpawnExplosion(((Component)doorLock).transform.position, false, 0f, 0f, 50, 15f, (GameObject)null, false);
			}
		}

		private static void CreateGhostHand(Component playerControllerB)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = playerControllerB.transform.position;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(position.x, position.y + 1f, position.z);
			Object obj = Object.Instantiate(MalfunctioningDoors.ghostHandPrefab, val, new Quaternion(0f, 0f, 0f, 0f));
			GameObject val2 = (GameObject)(object)((obj is GameObject) ? obj : null);
			if (val2 == null)
			{
				MalfunctioningDoors.Logger.LogFatal((object)"Something went wrong while trying to instantiate the GhostHands!");
				return;
			}
			val2.transform.LookAt(playerControllerB.transform);
			Transform transform = val2.transform;
			transform.rotation *= Quaternion.Euler(0f, 90f, 0f);
			val2.transform.position = val;
			Transform transform2 = val2.transform;
			transform2.localScale *= 1.8f;
			GhostHandRotator ghostHandRotator = val2.AddComponent<GhostHandRotator>();
			ghostHandRotator.playerControllerTransform = playerControllerB.transform;
		}

		public override void UseInteract(PlayerControllerB playerControllerB)
		{
		}

		public override void UseKey()
		{
		}

		public override bool ShouldExecute()
		{
			return _syncedRandom.Next(0, 100) <= _malfunctionChance && !IsDestroyed();
		}

		private void PlayGhostHandSound()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			int num = _syncedRandom.Next(0, MalfunctioningDoors.GhostHandSfxList.Length);
			AudioClip val = MalfunctioningDoors.GhostHandSfxList[num];
			MalfunctioningDoors.Logger.LogDebug((object)$"Playing clip '{((Object)val).name}' ({num})");
			GameObject val2 = new GameObject("TemporaryGhostHandAudio");
			AudioSource val3 = val2.AddComponent<AudioSource>();
			val3.clip = val;
			val3.volume = 2f;
			val3.Play();
			Object.Destroy((Object)(object)val2, val.length);
		}
	}
	[Malfunction(80)]
	public class NoYouMalfunction : MalfunctionalDoor
	{
		private static int _malfunctionChance = 35;

		private Random _syncedRandom = null;

		private void Start()
		{
			doorLock = ((Component)this).GetComponent<DoorLock>();
			_syncedRandom = DoorLockPatch.syncedRandom;
		}

		public static int OverrideWeight(ConfigFile configFile)
		{
			return configFile.Bind<int>("6. No You", "1. Malfunction Weight", 80, "Defines the weight of a malfunction. The higher, the more likely it is to appear").Value;
		}

		public new static void InitializeConfig(ConfigFile configFile)
		{
			_malfunctionChance = configFile.Bind<int>("6. No You", "2. Malfunction Chance", 35, "Defines the chance, if a malfunction is executed").Value;
		}

		public override void TouchInteract(PlayerControllerB playerControllerB)
		{
		}

		public override void UseInteract(PlayerControllerB playerControllerB)
		{
			if (doorLock != null)
			{
				int num = 1;
				if (_syncedRandom.Next(0, 2) > 0)
				{
					num = -num;
				}
				((MonoBehaviour)this).StartCoroutine(StartRotation(playerControllerB, num));
				playerControllerB.JumpToFearLevel(1f, true);
				DoorLocker component = ((Component)doorLock).gameObject.GetComponent<DoorLocker>();
				if (component == null)
				{
					MalfunctioningDoors.Logger.LogFatal((object)"No DoorLocker found?!");
				}
				else
				{
					component.SetDoorOpenServerRpc((int)playerControllerB.playerClientId, !doorLock.isDoorOpened);
				}
			}
		}

		private static IEnumerator StartRotation(PlayerControllerB playerControllerB, float direction)
		{
			float terminate = 1f;
			Quaternion startRotation = ((Component)playerControllerB).transform.rotation;
			float targetRotationY = ((Quaternion)(ref startRotation)).eulerAngles.y + 90f * direction;
			float currentAngle2 = ((Quaternion)(ref startRotation)).eulerAngles.y;
			float rotationSpeed = 0f;
			while (Quaternion.Angle(startRotation, ((Component)playerControllerB).transform.rotation) < 90f)
			{
				terminate -= Time.deltaTime;
				if (terminate <= 0f)
				{
					break;
				}
				float num = rotationSpeed;
				if (!(num < 10f))
				{
					if (num > 5f)
					{
						rotationSpeed -= Time.deltaTime * 5f;
					}
				}
				else
				{
					rotationSpeed += Time.deltaTime * 10f;
				}
				currentAngle2 += rotationSpeed * Time.deltaTime * 240f * direction;
				currentAngle2 = ((direction > 0f) ? Mathf.Clamp(currentAngle2, ((Quaternion)(ref startRotation)).eulerAngles.y, targetRotationY) : Mathf.Clamp(currentAngle2, targetRotationY, ((Quaternion)(ref startRotation)).eulerAngles.y));
				Vector3 position = ((Component)playerControllerB).transform.position;
				Quaternion val = Quaternion.Euler(0f, currentAngle2, 0f);
				playerControllerB.TeleportPlayer(position, true, ((Quaternion)(ref val)).eulerAngles.y, false, true);
				yield return (object)new WaitForEndOfFrame();
			}
		}

		public override void UseKey()
		{
		}

		public override bool ShouldExecute()
		{
			return _syncedRandom.Next(0, 100) <= _malfunctionChance && !IsDestroyed();
		}
	}
	[Malfunction(150)]
	public class RandomOpenCloseMalfunction : MalfunctionalDoor
	{
		private static int _malfunctionChance = 40;

		private Random _syncedRandom = null;

		private bool _waiting;

		private void Start()
		{
			doorLock = ((Component)this).GetComponent<DoorLock>();
			_syncedRandom = DoorLockPatch.syncedRandom;
		}

		private void Update()
		{
			if (_waiting)
			{
				return;
			}
			((MonoBehaviour)this).StartCoroutine(StartWaiting());
			if (doorLock == null)
			{
				return;
			}
			int num = _syncedRandom.Next(0, 100);
			if (num < _malfunctionChance)
			{
				DoorLocker component = ((Component)doorLock).gameObject.GetComponent<DoorLocker>();
				if (component == null)
				{
					MalfunctioningDoors.Logger.LogFatal((object)"No DoorLocker found?!");
					return;
				}
				bool flag = !doorLock.isDoorOpened;
				component.SetDoorOpenServerRpc(ActionSource.ToInt((Source)(-665)), flag);
			}
		}

		public static int OverrideWeight(ConfigFile configFile)
		{
			return configFile.Bind<int>("5. Random Open Close Malfunction", "1. Malfunction Weight", 150, "Defines the weight of a malfunction. The higher, the more likely it is to appear").Value;
		}

		public new static void InitializeConfig(ConfigFile configFile)
		{
			_malfunctionChance = configFile.Bind<int>("5. Random Open Close Malfunction", "2. Malfunction Chance", 40, "Defines the chance, if a malfunction is executed").Value;
		}

		public override void TouchInteract(PlayerControllerB playerControllerB)
		{
		}

		public override void UseInteract(PlayerControllerB playerControllerB)
		{
		}

		public override void UseKey()
		{
		}

		public override bool ShouldExecute()
		{
			return false;
		}

		private IEnumerator StartWaiting()
		{
			_waiting = true;
			yield return (object)new WaitForSeconds((float)_syncedRandom.Next(5, 30));
			_waiting = false;
		}
	}
}
namespace MalfunctioningDoors.Functional
{
	public class GhostHandRotator : MonoBehaviour
	{
		internal Transform? playerControllerTransform;

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(DestroyLater(3f));
		}

		private void Update()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)playerControllerTransform))
			{
				((Component)this).transform.LookAt(playerControllerTransform);
				Transform transform = ((Component)this).transform;
				transform.rotation *= Quaternion.Euler(0f, 90f, 0f);
			}
		}

		private IEnumerator DestroyLater(float waitForSeconds)
		{
			yield return (object)new WaitForSeconds(waitForSeconds);
			yield return (object)new WaitForEndOfFrame();
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}
}
namespace MalfunctioningDoors.Dependencies
{
	internal static class DependencyChecker
	{
		internal static bool IsLobbyCompatibilityInstalled()
		{
			return Chainloader.PluginInfos.Values.Any((PluginInfo metadata) => metadata.Metadata.GUID.Contains("LobbyCompatibility"));
		}
	}
	internal static class LobbyCompatibilitySupport
	{
		internal static void Initialize()
		{
			PluginHelper.RegisterPlugin("TestAccount666.MalfunctioningDoors", new Version("1.12.0"), (CompatibilityLevel)2, (VersionStrictness)2);
		}
	}
}
namespace TestAccount666.MalfunctioningDoors.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}