Decompiled source of RealBackroomsPatch v1.4.0

BepInEx/plugins/RealBackroomsPatch/RealBackroomsPatch.dll

Decompiled 3 weeks 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.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using Backrooms;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using GameNetcodeStuff;
using GroanTubeScrap;
using HarmonyLib;
using JetBrains.Annotations;
using LCSoundTool;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
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.RealBackroomsPatch")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Backrooms Patch, but real")]
[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: AssemblyInformationalVersion("1.4.0")]
[assembly: AssemblyProduct("RealBackroomsPatch")]
[assembly: AssemblyTitle("TestAccount666.RealBackroomsPatch")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 RealBackroomsPatch
{
	public class BackroomsConfig
	{
		private readonly ConfigFile _configFile;

		public ConfigEntry<DropHeldItemsMode> DropHeldItemsMode { get; private set; }

		public ConfigEntry<bool> ShouldPreventDamageTeleport { get; private set; }

		public ConfigEntry<bool> ShouldPreventDeathTeleport { get; private set; }

		public ConfigEntry<bool> ShouldPreventNegativeDamageTeleport { get; private set; }

		[CanBeNull]
		public ConfigEntry<bool> ShouldSpawnDeadBody { get; private set; } = null;


		public ConfigEntry<bool> ShouldTeleportAnnoyingPeople { get; private set; }

		[CanBeNull]
		public ConfigEntry<bool> ShouldTeleportToAndReplaceDeadBody { get; private set; } = null;


		public ConfigEntry<int> TeleportAnnoyingPeopleChance { get; private set; }

		public ConfigEntry<int> TeleportLethalDamageChance { get; private set; }

		public ConfigEntry<int> TeleportNonLethalDamageChance { get; private set; }

		public ConfigEntry<string> PreventBackroomsTeleportEnemies { get; private set; }

		public ConfigEntry<int> LightFlickerSmoothing { get; private set; }

		public ConfigEntry<float> LightFlickerMinIntensity { get; private set; }

		public ConfigEntry<float> LightFlickerMaxIntensity { get; private set; }

		public ConfigEntry<bool> PlayMusic { get; private set; }

		public BackroomsConfig(string guid, ConfigFile configFile)
		{
			_configFile = configFile;
			HandleConfig();
			RemoveOrphans();
			Plugin.InfoLog("Printing Config:");
			Plugin.InfoLog($"DropHeldItemsMode: {DropHeldItemsMode.Value}");
			Plugin.InfoLog($"ShouldPreventDamageTeleport: {ShouldPreventDamageTeleport.Value}");
			Plugin.InfoLog($"ShouldPreventDeathTeleport: {ShouldPreventDeathTeleport.Value}");
			Plugin.InfoLog($"ShouldPreventNegativeDamageTeleport: {ShouldPreventNegativeDamageTeleport.Value}");
			Plugin.InfoLog($"ShouldTeleportAnnoyingPeople: {ShouldTeleportAnnoyingPeople.Value}");
			Plugin.InfoLog($"TeleportAnnoyingPeopleChance: {TeleportAnnoyingPeopleChance.Value}");
			Plugin.InfoLog($"TeleportLethalDamageChance: {TeleportLethalDamageChance.Value}");
			Plugin.InfoLog($"TeleportNonLethalDamageChance: {TeleportNonLethalDamageChance.Value}");
			Plugin.InfoLog("PreventBackroomsTeleportEnemies: " + PreventBackroomsTeleportEnemies.Value);
		}

		private void HandleConfig()
		{
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Expected O, but got Unknown
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Expected O, but got Unknown
			Plugin.InfoLog("Handling Config!");
			ShouldPreventDamageTeleport = _configFile.Bind<bool>("Teleport", "Prevent damage teleport", true, "If true, will prevent the backrooms mod from teleporting players that received damage");
			ShouldPreventDeathTeleport = _configFile.Bind<bool>("Teleport", "Prevent death teleport", false, "If true, will prevent the backrooms mod from teleporting players that received deadly damage");
			ShouldPreventNegativeDamageTeleport = _configFile.Bind<bool>("Teleport", "Prevent negative damage teleport", false, "If true, will prevent the backrooms mod from teleporting players that received negative damage (Aka healing)");
			DropHeldItemsMode = _configFile.Bind<DropHeldItemsMode>("Teleport", "Drop held items on teleport", RealBackroomsPatch.DropHeldItemsMode.DropNothing, "When do you want items to be dropped when teleported into the backrooms?");
			PreventBackroomsTeleportEnemies = _configFile.Bind<string>("Teleport", "Prevent backrooms when attacked by enemies", "Flowerman, MaskedPlayer", "A list of enemies that will not allow you to spawn in the backrooms, if attacked by them (Needs internal name. Example: Flowerman, Jester, ...)");
			TeleportLethalDamageChance = _configFile.Bind<int>("Chances", "Teleport lethal damage chance", 1, "The chance that a person will get teleported into the backrooms with lethal damage (Requires \"Prevent death teleport\" set to \"false\")");
			TeleportNonLethalDamageChance = _configFile.Bind<int>("Chances", "Teleport non-lethal damage chance", 3, "The chance that a person will get teleported into the backrooms with non-lethal damage (Requires \"Prevent damage teleport\" set to \"false\")");
			ShouldTeleportAnnoyingPeople = _configFile.Bind<bool>("Extra", "Teleport annoying people", false, "If true, will teleport annoying people (e.g. People using horns)");
			TeleportAnnoyingPeopleChance = _configFile.Bind<int>("Extra", "Teleport annoying people chance", 10, "The chance that annoying people can get teleported");
			LightFlickerSmoothing = _configFile.Bind<int>("Light Flickering", "Smoothing", 25, new ConfigDescription("How much to smooth out the randomness; lower values = sparks, higher = lantern", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>()));
			LightFlickerMinIntensity = _configFile.Bind<float>("Light Flickering", "Min intensity", 0.2f, new ConfigDescription("Minimum random light intensity", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			LightFlickerMaxIntensity = _configFile.Bind<float>("Light Flickering", "Max intensity", 1.5f, new ConfigDescription("Maximum random light intensity", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			PlayMusic = _configFile.Bind<bool>("Music", "Play Music", true, "If true, plays music in the backrooms");
			Plugin.InfoLog("Handled Config!");
		}

		private void RemoveOrphans()
		{
			PropertyInfo property = ((object)_configFile).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
			if (!(property == null))
			{
				Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(_configFile, null);
				dictionary.Clear();
				_configFile.Save();
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	public class DebugPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		public static void PrintConfigOnStart()
		{
			Plugin.InfoLog("Printing Config:");
			Plugin.InfoLog($"DropHeldItemsMode: {Plugin.backroomsConfig.DropHeldItemsMode.Value}");
			Plugin.InfoLog($"ShouldPreventDamageTeleport: {Plugin.backroomsConfig.ShouldPreventDamageTeleport.Value}");
			Plugin.InfoLog($"ShouldPreventDeathTeleport: {Plugin.backroomsConfig.ShouldPreventDeathTeleport.Value}");
			Plugin.InfoLog($"ShouldPreventNegativeDamageTeleport: {Plugin.backroomsConfig.ShouldPreventNegativeDamageTeleport.Value}");
			Plugin.InfoLog($"ShouldTeleportAnnoyingPeople: {Plugin.backroomsConfig.ShouldTeleportAnnoyingPeople.Value}");
			Plugin.InfoLog($"TeleportAnnoyingPeopleChance: {Plugin.backroomsConfig.TeleportAnnoyingPeopleChance.Value}");
			Plugin.InfoLog($"TeleportLethalDamageChance: {Plugin.backroomsConfig.TeleportLethalDamageChance.Value}");
			Plugin.InfoLog($"TeleportNonLethalDamageChance: {Plugin.backroomsConfig.TeleportNonLethalDamageChance.Value}");
			Plugin.InfoLog("PreventBackroomsTeleportEnemies: " + Plugin.backroomsConfig.PreventBackroomsTeleportEnemies.Value);
		}
	}
	public static class DependencyChecker
	{
		public static bool IsGroanTubeModInstalled()
		{
			return Chainloader.PluginInfos.Values.Any((PluginInfo metadata) => metadata.Metadata.GUID.Equals("Kittenji.GroanTubeScrap"));
		}

		public static bool IsSoundToolsModInstalled()
		{
			return Chainloader.PluginInfos.Values.Any((PluginInfo metadata) => metadata.Metadata.GUID.Equals("LCSoundTool"));
		}
	}
	[DataContract]
	public enum DropHeldItemsMode
	{
		[EnumMember]
		DropNothing,
		[EnumMember]
		DropAll,
		[EnumMember]
		DropAllOnDeath,
		[EnumMember]
		DropAllOnAnnoying,
		[EnumMember]
		DropAllOnAnnoyingAndDeath
	}
	[HarmonyPatch]
	public class GroanTubePatch
	{
		public static MethodBase TargetMethod()
		{
			Type type2 = AccessTools.GetTypesFromAssembly(typeof(Loader).Assembly).FirstOrDefault((Type type1) => type1.Name.Contains("GroanTubeItem"));
			return (type2 == null) ? null : AccessTools.FirstMethod(type2, (Func<MethodInfo, bool>)((MethodInfo method) => method.Name.Contains("ItemActivate")));
		}

		public static void Prefix(NoisemakerProp __instance)
		{
			if (!((GrabbableObject)__instance).isHeld)
			{
				Plugin.WarningLog("Groan Tube not held!");
			}
			else
			{
				Patches.TeleportForAnnoyingPeople(((GrabbableObject)__instance).playerHeldBy);
			}
		}
	}
	[RequireComponent(typeof(SphereCollider))]
	public class FixedKillBox : MonoBehaviour
	{
		public void OnTriggerEnter(Collider other)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB component = ((Component)other).gameObject.GetComponent<PlayerControllerB>();
			if (!((Object)(object)component == (Object)null))
			{
				component.KillPlayer(Vector3.zero, true, (CauseOfDeath)0, 0, default(Vector3));
			}
		}
	}
	[HarmonyPatch(typeof(LightFlickerEffect))]
	public static class LightFlickerEffectPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPostfix(LightFlickerEffect __instance)
		{
			__instance.smoothing = Plugin.backroomsConfig.LightFlickerSmoothing.Value;
			__instance.minIntensity = Plugin.backroomsConfig.LightFlickerMinIntensity.Value;
			__instance.maxIntensity = Plugin.backroomsConfig.LightFlickerMaxIntensity.Value;
		}
	}
	public class MusicPlayer : MonoBehaviour
	{
		private const int MUSIC_COOLDOWN = 1000;

		private const float VOLUME_DECREASE_STEP = 0.05f;

		private readonly Random _random = new Random();

		[CanBeNull]
		private AudioSource _audioSource;

		private int? _instanceId;

		private long _nextTimePlaying = UnixTime.GetCurrentTime() + 1000;

		private bool _shouldStop;

		private void Update()
		{
			if (_shouldStop)
			{
				return;
			}
			long currentTime = UnixTime.GetCurrentTime();
			if (_nextTimePlaying <= currentTime)
			{
				int? instanceId = _instanceId;
				if (!instanceId.HasValue || Object.FindObjectFromInstanceID(_instanceId.Value) == null)
				{
					PlayMusic();
				}
			}
		}

		private void PlayMusic()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			long currentTime = UnixTime.GetCurrentTime();
			int num = _random.Next(0, Plugin.MusicSounds.Count);
			AudioClip val = Plugin.MusicSounds[num];
			Plugin.DebugLog($"Playing clip '{((Object)val).name}' ({num})");
			GameObject val2 = new GameObject("TemporaryMusicAudio");
			_instanceId = ((Object)val2).GetInstanceID();
			_audioSource = val2.AddComponent<AudioSource>();
			Debug.Assert((Object)(object)_audioSource != (Object)null, "_audioSource != null");
			_audioSource.clip = val;
			_audioSource.volume = 0.5f;
			_audioSource.Play();
			_nextTimePlaying = (long)((float)(currentTime + 1000) + val.length * 1000f);
			Object.Destroy((Object)(object)val2, val.length);
		}

		public void Stop()
		{
			_shouldStop = true;
			((MonoBehaviour)this).StartCoroutine(FadeOutMusic());
		}

		private void TerminateMusic()
		{
			if (_instanceId.HasValue)
			{
				Object val = Object.FindObjectFromInstanceID(_instanceId.Value);
				if (val == (Object)null)
				{
					return;
				}
				Object.Destroy(val);
			}
			Object.Destroy((Object)(object)this);
		}

		private IEnumerator FadeOutMusic()
		{
			if ((Object)(object)_audioSource == (Object)null)
			{
				TerminateMusic();
				yield break;
			}
			if (!_audioSource.isPlaying)
			{
				TerminateMusic();
				yield break;
			}
			AudioSource audioSource = _audioSource;
			audioSource.volume -= 0.05f * Time.deltaTime;
			if (_audioSource.volume <= 0f)
			{
				TerminateMusic();
				yield break;
			}
			yield return (object)new WaitForEndOfFrame();
			yield return FadeOutMusic();
		}
	}
	[HarmonyPatch]
	public static class Patches
	{
		private static readonly List<ulong> _ImmortalPlayers = new List<ulong>();

		private static readonly int _BiohazardDamage = Animator.StringToHash("biohazardDamage");

		public static void UnpatchDamagePlayerMethod([NotNull] Harmony harmony)
		{
			if (!Unpatch<PlayerControllerB>(harmony, "DamagePlayer", "BeforeDamage"))
			{
				Plugin.ErrorLog("Failed to unpatch DamagePlayer!");
			}
		}

		public static void UnpatchKillPlayerMethod([NotNull] Harmony harmony)
		{
			if (!Unpatch<KillLocalPlayer>(harmony, "KillPlayer", "BeforeKilling"))
			{
				Plugin.ErrorLog("Failed to unpatch KillPlayer!");
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")]
		[HarmonyPrefix]
		public static bool TeleportOnDamage(int damageNumber, CauseOfDeath causeOfDeath, Vector3 force, int deathAnimation, PlayerControllerB __instance)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			bool lethalDamage = __instance.health - damageNumber <= 0;
			bool negativeDamage = damageNumber <= 0;
			Plugin.InfoLog("TeleportOnDamage!");
			if (!MeetRequirementsForBackrooms(__instance, lethalDamage, negativeDamage))
			{
				return true;
			}
			RpcCollection.Instance.TeleportPlayerToBackroomsServerRpc((int)__instance.playerClientId, spawnBody: false, force, causeOfDeath, deathAnimation, lethalDamage, negativeDamage);
			return false;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
		[HarmonyPrefix]
		public static bool TeleportOnKill(Vector3 bodyVelocity, bool spawnBody, CauseOfDeath causeOfDeath, int deathAnimation, Vector3 positionOffset, PlayerControllerB __instance)
		{
			//IL_0046: 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)
			Plugin.InfoLog("TeleportOnKill!");
			if (Plugin.backroomsConfig.ShouldPreventDeathTeleport.Value)
			{
				return true;
			}
			if (!MeetRequirementsForBackrooms(__instance))
			{
				return true;
			}
			RpcCollection.Instance.TeleportPlayerToBackroomsServerRpc((int)__instance.playerClientId, spawnBody, bodyVelocity, causeOfDeath, deathAnimation);
			return false;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "AllowPlayerDeath")]
		[HarmonyPrefix]
		public static bool PreventPlayerDeath(ref bool __result, PlayerControllerB __instance)
		{
			if (Plugin.backroomsConfig.ShouldPreventDeathTeleport.Value)
			{
				return true;
			}
			if (!_ImmortalPlayers.Contains(__instance.playerSteamId))
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPatch(typeof(NoisemakerProp), "ItemActivate")]
		[HarmonyPrefix]
		public static void TeleportForAnnoyingPeople(PlayerControllerB ___playerHeldBy)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.backroomsConfig.ShouldTeleportAnnoyingPeople.Value && MeetRequirementsForBackrooms(___playerHeldBy, lethalDamage: false, negativeDamage: false, annoying: true))
			{
				RpcCollection.Instance.TeleportPlayerToBackroomsServerRpc((int)___playerHeldBy.playerClientId, spawnBody: false, default(Vector3), (CauseOfDeath)0, 0, lethalDamage: false, negativeDamage: false, annoying: true);
			}
		}

		[HarmonyPatch(typeof(Backrooms), "TeleportOutOfBackroomsClientRpc")]
		[HarmonyPostfix]
		public static void RestoreVanillaSounds(int client)
		{
			if (client == (int)StartOfRound.Instance.localPlayerController.playerClientId)
			{
				if (Plugin.enableSoundReplace)
				{
					SoundToolsWrapper.RestoreAudioClip("WoodStep1");
					SoundToolsWrapper.RestoreAudioClip("WoodStep2");
					SoundToolsWrapper.RestoreAudioClip("WoodStep3");
					SoundToolsWrapper.RestoreAudioClip("WoodStep4");
				}
				MusicPlayer component = ((Component)StartOfRound.Instance.localPlayerController).GetComponent<MusicPlayer>();
				if (!((Object)(object)component == (Object)null))
				{
					component.Stop();
				}
			}
		}

		[HarmonyPatch(typeof(Backrooms), "TeleportOutOfBackroomsClientRpc")]
		[HarmonyPostfix]
		public static void TeleportToAndReplaceDeadBody(int client, Backrooms ___Instance)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Invalid comparison between Unknown and I4
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.backroomsConfig.ShouldTeleportToAndReplaceDeadBody == null)
			{
				return;
			}
			Debug.Assert(Plugin.backroomsConfig.ShouldTeleportToAndReplaceDeadBody != null, "Plugin.BackroomsConfig.ShouldTeleportToAndReplaceDeadBody != null");
			if (!Plugin.backroomsConfig.ShouldTeleportToAndReplaceDeadBody.Value)
			{
				return;
			}
			PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[client];
			DeadBodyInfo deadBody = val.deadBody;
			if (!((Object)(object)deadBody == (Object)null) && !deadBody.deactivated && (deadBody.grabBodyObject.isInShipRoom || !deadBody.grabBodyObject.isInFactory || (int)deadBody.causeOfDeath != 2))
			{
				Vector3 itemFloorPosition = deadBody.grabBodyObject.GetItemFloorPosition(default(Vector3));
				bool isInFactory = deadBody.grabBodyObject.isInFactory;
				bool isInShipRoom = deadBody.grabBodyObject.isInShipRoom;
				bool isInElevator = deadBody.grabBodyObject.isInElevator;
				Vector3 spawnPosition = deadBody.spawnPosition;
				spawnPosition.x += Vector3.down.x * 200f;
				spawnPosition.y += Vector3.down.y * 200f;
				spawnPosition.z += Vector3.down.z * 200f;
				deadBody.SetRagdollPositionSafely(spawnPosition, true);
				if (((NetworkBehaviour)Backrooms.Instance).IsHost || ((NetworkBehaviour)Backrooms.Instance).IsServer)
				{
					val.SyncBodyPositionWithClients();
					((NetworkBehaviour)deadBody.grabBodyObject).NetworkObject.Despawn(true);
				}
				val.deadBody = null;
				val.TeleportPlayer(itemFloorPosition, false, 0f, false, true);
				val.isInsideFactory = isInFactory;
				val.isInHangarShipRoom = isInShipRoom;
				val.isInElevator = isInElevator;
			}
		}

		private static bool CompareMethodInfoAndMethodBase(MethodInfo methodInfo, MethodBase methodBase)
		{
			if (methodInfo == null)
			{
				return false;
			}
			if (methodBase == null)
			{
				return false;
			}
			if (methodInfo.DeclaringType == null)
			{
				return false;
			}
			if (methodBase.DeclaringType == null)
			{
				return false;
			}
			bool flag = methodInfo.Name == methodBase.Name;
			Debug.Assert(methodInfo.DeclaringType.FullName != null, "methodInfo.DeclaringType.FullName != null");
			bool flag2 = methodInfo.DeclaringType.FullName.Equals(methodBase.DeclaringType.FullName);
			return flag && flag2;
		}

		private static bool Unpatch<T>([NotNull] Harmony harmony, [NotNull] string originalMethodName, [NotNull] string backroomsMethodName)
		{
			MethodInfo methodInfo = typeof(T).GetMethods().FirstOrDefault((MethodInfo method) => method.Name.Equals(originalMethodName));
			MethodInfo method2 = typeof(Hook).GetMethod(backroomsMethodName, BindingFlags.Static | BindingFlags.NonPublic);
			foreach (MethodBase allPatchedMethod in Harmony.GetAllPatchedMethods())
			{
				if (!CompareMethodInfoAndMethodBase(methodInfo, allPatchedMethod))
				{
					continue;
				}
				Patches patchInfo = Harmony.GetPatchInfo(allPatchedMethod);
				if (patchInfo == null)
				{
					Plugin.ErrorLog("Failed to retrieve patch information for method: " + allPatchedMethod.Name);
					continue;
				}
				foreach (Patch prefix in patchInfo.Prefixes)
				{
					MethodInfo method3 = prefix.GetMethod((MethodBase)method2);
					if (!CompareMethodInfoAndMethodBase(method2, method3))
					{
						continue;
					}
					harmony.Unpatch((MethodBase)methodInfo, (HarmonyPatchType)1, prefix.owner);
					Plugin.InfoLog("Unpatched " + originalMethodName + " method!");
					return true;
				}
			}
			Plugin.ErrorLog("Target method not found: " + originalMethodName);
			return false;
		}

		private static void DisablePlayerDeath(int secondsFor, PlayerControllerB player)
		{
			_ImmortalPlayers.Add(player.playerSteamId);
			Timer timer = null;
			timer = new Timer(delegate
			{
				_ImmortalPlayers.Remove(player.playerSteamId);
				timer?.Dispose();
			}, null, secondsFor * 1000, -1);
		}

		internal static void SpawnDeadBody(PlayerControllerB player, Vector3 bodyVelocity, CauseOfDeath causeOfDeath, int deathAnimation, EnemyAI enemyAI, bool isServer = true)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected I4, but got Unknown
			string text = $"PositionObject-{player.playerClientId}-{SystemClock.ToUnixTimeMilliseconds(SystemClock.now)}";
			GameObject val = new GameObject(text);
			Transform transform = val.transform;
			transform.position = player.oldPlayerPosition;
			transform.rotation = player.thisPlayerBody.rotation;
			if (isServer)
			{
				GameObject val2 = Object.Instantiate<GameObject>(StartOfRound.Instance.ragdollGrabbableObjectPrefab, player.playersManager.propsContainer);
				val2.GetComponent<NetworkObject>().Spawn(false);
				val2.GetComponent<RagdollGrabbableObject>().bodyID.Value = (int)player.playerClientId;
			}
			player.SpawnDeadBody((int)player.playerClientId, bodyVelocity, (int)causeOfDeath, player, deathAnimation, transform, default(Vector3));
			player.deadBody.canBeGrabbedBackByPlayers = true;
			if (isServer)
			{
				player.SyncBodyPositionWithClients();
			}
			if (!((Object)(object)enemyAI == (Object)null))
			{
				FlowermanAI val3 = (FlowermanAI)(object)((enemyAI is FlowermanAI) ? enemyAI : null);
				if (val3 != null)
				{
					((EnemyAI)val3).inSpecialAnimationWithPlayer = player;
					val3.FinishKillAnimation(true);
				}
			}
		}

		private static void EnemyFixes(EnemyAI enemyAI)
		{
			FlowermanAI val = (FlowermanAI)(object)((enemyAI is FlowermanAI) ? enemyAI : null);
			if (val == null)
			{
				MaskedPlayerEnemy val2 = (MaskedPlayerEnemy)(object)((enemyAI is MaskedPlayerEnemy) ? enemyAI : null);
				if (val2 != null)
				{
					if ((Object)(object)((EnemyAI)val2).inSpecialAnimationWithPlayer == (Object)(object)GameNetworkManager.Instance.localPlayerController)
					{
						HUDManager.Instance.HUDAnimator.SetBool(_BiohazardDamage, false);
						HUDManager.Instance.HideHUD(true);
						HUDManager.Instance.HideHUD(false);
					}
					val2.FinishKillAnimation(false);
					((EnemyAI)val2).inSpecialAnimationWithPlayer = null;
				}
			}
			else
			{
				val.FinishKillAnimation(false);
				((EnemyAI)val).inSpecialAnimation = false;
			}
		}

		private static bool MeetRequirementsForBackrooms(PlayerControllerB player, bool lethalDamage = true, bool negativeDamage = false, bool annoying = false)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			Plugin.InfoLog("Player exists!");
			if (player.isPlayerDead || !player.AllowPlayerDeath() || ((Component)player).GetComponent<BackroomsHelper>().HasBeenInTheBackrooms)
			{
				return false;
			}
			Plugin.InfoLog("Passed checks!");
			if (negativeDamage && Plugin.backroomsConfig.ShouldPreventNegativeDamageTeleport.Value)
			{
				return false;
			}
			Plugin.InfoLog("Negative damage check passed!");
			Plugin.InfoLog("Prevent Death Teleport: " + Plugin.backroomsConfig.ShouldPreventDeathTeleport.Value);
			Plugin.InfoLog("Prevent Damage Teleport: " + Plugin.backroomsConfig.ShouldPreventDamageTeleport.Value);
			if (!annoying)
			{
				if ((lethalDamage && Plugin.backroomsConfig.ShouldPreventDeathTeleport.Value) || (!lethalDamage && Plugin.backroomsConfig.ShouldPreventDamageTeleport.Value))
				{
					goto IL_0122;
				}
			}
			else if (!Plugin.backroomsConfig.ShouldTeleportAnnoyingPeople.Value)
			{
				goto IL_0122;
			}
			Plugin.InfoLog("Lethal or not and Annoying check passed!");
			EnemyAI inAnimationWithEnemy = player.inAnimationWithEnemy;
			List<string> list = Plugin.backroomsConfig.PreventBackroomsTeleportEnemies.Value.ToLower().Replace(" ", "").Split(",")
				.ToList();
			if ((Object)(object)inAnimationWithEnemy != (Object)null && list.Contains(inAnimationWithEnemy.enemyType.enemyName.ToLower()))
			{
				return false;
			}
			Plugin.InfoLog("AI check passed!");
			int value = (annoying ? Plugin.backroomsConfig.TeleportAnnoyingPeopleChance : (lethalDamage ? Plugin.backroomsConfig.TeleportLethalDamageChance : Plugin.backroomsConfig.TeleportNonLethalDamageChance)).Value;
			Plugin.InfoLog($"Teleport chance: {value}!");
			int num = Random.Range(1, 100);
			Plugin.InfoLog($"Rolled chance: {num}!");
			if (num > value)
			{
				return false;
			}
			Plugin.InfoLog("Chance check passed!");
			return true;
			IL_0122:
			return false;
		}

		internal static void TeleportPlayerToBackrooms(PlayerControllerB player, bool spawnBody = false, Vector3 bodyVelocity = default(Vector3), CauseOfDeath causeOfDeath = 0, int deathAnimation = 0, bool lethalDamage = true, bool annoying = false)
		{
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			Plugin.InfoLog("Teleport To Backrooms method!");
			EnemyAI inAnimationWithEnemy = player.inAnimationWithEnemy;
			int enemyId = (((Object)(object)inAnimationWithEnemy == (Object)null) ? (-1) : inAnimationWithEnemy.thisEnemyIndex);
			EnemyFixes(inAnimationWithEnemy);
			Plugin.InfoLog("Enemy Fixes passed!");
			if (ShouldDropItems(lethalDamage, annoying))
			{
				player.DropAllHeldItemsAndSync();
			}
			DisablePlayerDeath(2, player);
			Plugin.InfoLog("Sending player to backrooms!");
			Backrooms.Instance.TeleportToBackroomsServerRpc((int)player.playerClientId);
			if (Plugin.enableSoundReplace && player.playerClientId == StartOfRound.Instance.localPlayerController.playerClientId)
			{
				for (int i = 1; i <= 4; i++)
				{
					int num = i - 1;
					AudioClip newClip = Plugin.CarpetSounds[num];
					SoundToolsWrapper.ReplaceAudioClip($"WoodStep{i}", newClip);
				}
				((Component)player).gameObject.AddComponent<MusicPlayer>();
			}
			if (Plugin.backroomsConfig.ShouldSpawnDeadBody != null)
			{
				Debug.Assert(Plugin.backroomsConfig.ShouldSpawnDeadBody != null, "Plugin.BackroomsConfig.ShouldSpawnDeadBody != null");
				if (Plugin.backroomsConfig.ShouldSpawnDeadBody.Value && spawnBody)
				{
					Plugin.InfoLog("Spawning body!");
					RpcCollection.Instance.SpawnDeadBodyServerRpc((int)player.playerClientId, bodyVelocity, causeOfDeath, deathAnimation, enemyId);
				}
			}
		}

		private static bool ShouldDropItems(bool lethalDamage, bool annoying)
		{
			int num;
			switch (Plugin.backroomsConfig.DropHeldItemsMode.Value)
			{
			case DropHeldItemsMode.DropAllOnAnnoyingAndDeath:
				num = 0;
				goto IL_003a;
			case DropHeldItemsMode.DropAllOnDeath:
				num = 1;
				goto IL_003a;
			case DropHeldItemsMode.DropAllOnAnnoying:
				if (!annoying)
				{
					break;
				}
				goto case DropHeldItemsMode.DropAll;
			case DropHeldItemsMode.DropAll:
				{
					return true;
				}
				IL_003a:
				if (!lethalDamage)
				{
					if (num == 0)
					{
						goto case DropHeldItemsMode.DropAllOnAnnoying;
					}
					if (num == 1)
					{
						break;
					}
				}
				goto case DropHeldItemsMode.DropAll;
			}
			return false;
		}
	}
	[BepInPlugin("TestAccount666.RealBackroomsPatch", "RealBackroomsPatch", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const int CARPET_SOUNDS_SIZE = 4;

		private static Plugin _instance;

		public static BackroomsConfig backroomsConfig;

		public static readonly AudioClip[] CarpetSounds = (AudioClip[])(object)new AudioClip[4];

		public static bool enableSoundReplace;

		public static readonly List<AudioClip> MusicSounds = new List<AudioClip>();

		private void Awake()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			_instance = this;
			WarningLog("This Mod is my very first Mod and is still work in progress.");
			backroomsConfig = new BackroomsConfig("TestAccount666.RealBackroomsPatch", ((BaseUnityPlugin)this).Config);
			Harmony val = new Harmony("TestAccount666.RealBackroomsPatch");
			InfoLog("Creating patches!");
			val.PatchAll(typeof(Patches));
			val.PatchAll(typeof(LightFlickerEffect));
			val.PatchAll(typeof(RpcCollectionLoader));
			val.PatchAll(typeof(SmilerPatch));
			if (DependencyChecker.IsGroanTubeModInstalled())
			{
				val.PatchAll(typeof(GroanTubePatch));
			}
			enableSoundReplace = DependencyChecker.IsSoundToolsModInstalled();
			InfoLog("Unpatching Backrooms Mod!");
			Patches.UnpatchDamagePlayerMethod(val);
			Patches.UnpatchKillPlayerMethod(val);
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				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);
					}
				}
			}
			((MonoBehaviour)this).StartCoroutine(LoadAudioClips());
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin RealBackroomsPatch is loaded!");
		}

		internal static void DebugLog(string msg)
		{
			((BaseUnityPlugin)_instance).Logger.LogDebug((object)msg);
		}

		internal static void InfoLog(string msg)
		{
			((BaseUnityPlugin)_instance).Logger.LogInfo((object)msg);
		}

		internal static void WarningLog(string msg)
		{
			((BaseUnityPlugin)_instance).Logger.LogWarning((object)msg);
		}

		internal static void ErrorLog(string msg)
		{
			((BaseUnityPlugin)_instance).Logger.LogError((object)msg);
		}

		private static IEnumerator LoadAudioClips()
		{
			string assemblyDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			InfoLog("Loading Carpet Step Sounds...");
			Debug.Assert(assemblyDirectory != null, "assemblyDirectory != null");
			string audioPath = Path.Combine(assemblyDirectory, "sounds");
			audioPath = (Directory.Exists(audioPath) ? audioPath : Path.Combine(assemblyDirectory));
			string carpetAudioPath2 = Path.Combine(audioPath, "CarpetSound");
			carpetAudioPath2 = (Directory.Exists(carpetAudioPath2) ? carpetAudioPath2 : Path.Combine(assemblyDirectory));
			for (int index = 1; index <= 4; index++)
			{
				int sound = index - 1;
				AudioClip carpetAudioClip = LoadAudioClipFromFile(new Uri(Path.Combine(carpetAudioPath2, $"CarpetStep{index}.wav")), $"CarpetStep{index}", (AudioType)20);
				CarpetSounds[sound] = carpetAudioClip;
				InfoLog("Loaded clip '" + ((Object)carpetAudioClip).name + "'!");
			}
			InfoLog("Loading Music...");
			string musicAudioPath2 = Path.Combine(audioPath, "Music");
			musicAudioPath2 = (Directory.Exists(musicAudioPath2) ? musicAudioPath2 : Path.Combine(assemblyDirectory));
			foreach (string file in Directory.EnumerateFiles(musicAudioPath2))
			{
				string fileName = Path.GetFileName(file);
				if (fileName.ToLower().EndsWith(".ogg") && fileName.ToLower().StartsWith("music"))
				{
					Uri filePath = new Uri(file);
					string text = fileName;
					AudioClip musicAudioClip = LoadAudioClipFromFile(filePath, text.Substring(0, text.Length - 4), (AudioType)14);
					MusicSounds.Add(musicAudioClip);
					InfoLog("Loaded clip '" + ((Object)musicAudioClip).name + "'!");
				}
			}
			yield break;
		}

		private static AudioClip LoadAudioClipFromFile(Uri filePath, string name, AudioType audioType = 20)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(filePath, audioType);
			try
			{
				UnityWebRequestAsyncOperation val = audioClip.SendWebRequest();
				while (!((AsyncOperation)val).isDone)
				{
					Thread.Sleep(100);
				}
				if ((int)audioClip.result != 1)
				{
					ErrorLog("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 PluginInfo
	{
		public const string PLUGIN_GUID = "TestAccount666.RealBackroomsPatch";

		public const string PLUGIN_NAME = "RealBackroomsPatch";

		public const string PLUGIN_VERSION = "1.1.0";
	}
	public class RpcCollection : NetworkBehaviour
	{
		public static RpcCollection Instance { get; private set; }

		public override void OnNetworkSpawn()
		{
			Plugin.InfoLog("RpcCollection network spawned!");
			if ((Object)(object)NetworkManager.Singleton == (Object)null)
			{
				Plugin.ErrorLog("NetworkManager.Singleton couldn't be found?!");
				return;
			}
			if ((NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) && (Object)(object)Instance != (Object)null && (Object)(object)((Component)Instance).gameObject != (Object)null)
			{
				((Component)Instance).gameObject.GetComponent<NetworkObject>().Despawn(true);
			}
			Instance = this;
		}

		[ClientRpc]
		public void SpawnDeadBodyClientRpc(int playerId, Vector3 bodyVelocity, CauseOfDeath causeOfDeath, int deathAnimation, int enemyId)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			Plugin.InfoLog("Spawn dead body ClientRpc!");
			PlayerControllerB player = StartOfRound.Instance.allPlayerScripts[playerId];
			EnemyAI enemyAI = ((enemyId != -1) ? RoundManager.Instance.SpawnedEnemies[enemyId] : null);
			Patches.SpawnDeadBody(player, bodyVelocity, causeOfDeath, deathAnimation, enemyAI, ((NetworkBehaviour)this).IsServer);
		}

		[ServerRpc(RequireOwnership = false)]
		public void SpawnDeadBodyServerRpc(int playerId, Vector3 bodyVelocity, CauseOfDeath causeOfDeath, int deathAnimation, int enemyId)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Plugin.InfoLog("Spawn body ServerRpc!");
			PlayerControllerB player = StartOfRound.Instance.allPlayerScripts[playerId];
			EnemyAI enemyAI = ((enemyId != -1) ? RoundManager.Instance.SpawnedEnemies[enemyId] : null);
			if (((NetworkBehaviour)this).IsServer && !((NetworkBehaviour)this).IsHost)
			{
				Plugin.InfoLog("Server spawning DeadBody!");
				Patches.SpawnDeadBody(player, bodyVelocity, causeOfDeath, deathAnimation, enemyAI, ((NetworkBehaviour)this).IsServer);
			}
			else
			{
				SpawnDeadBodyClientRpc(playerId, bodyVelocity, causeOfDeath, deathAnimation, enemyId);
			}
		}

		[ClientRpc]
		public void TeleportPlayerToBackroomsClientRpc(int playerId, bool spawnBody = false, Vector3 bodyVelocity = default(Vector3), CauseOfDeath causeOfDeath = 0, int deathAnimation = 0, bool lethalDamage = true, bool negativeDamage = false, bool annoying = false)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			Plugin.InfoLog("Teleport Player ClientRcp!");
			PlayerControllerB player = StartOfRound.Instance.allPlayerScripts[playerId];
			Patches.TeleportPlayerToBackrooms(player, spawnBody, bodyVelocity, causeOfDeath, deathAnimation, lethalDamage, annoying);
		}

		[ServerRpc(RequireOwnership = false)]
		public void TeleportPlayerToBackroomsServerRpc(int playerId, bool spawnBody = false, Vector3 bodyVelocity = default(Vector3), CauseOfDeath causeOfDeath = 0, int deathAnimation = 0, bool lethalDamage = true, bool negativeDamage = false, bool annoying = false)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			Plugin.InfoLog("Teleport Player ServerRcp!");
			PlayerControllerB player = StartOfRound.Instance.allPlayerScripts[playerId];
			if (((NetworkBehaviour)this).IsServer && !((NetworkBehaviour)this).IsHost)
			{
				Plugin.InfoLog("Server but not host Teleport!");
				Patches.TeleportPlayerToBackrooms(player, spawnBody, bodyVelocity, causeOfDeath, deathAnimation, lethalDamage, annoying);
			}
			TeleportPlayerToBackroomsClientRpc(playerId, spawnBody, bodyVelocity, causeOfDeath, deathAnimation, lethalDamage, negativeDamage, annoying);
		}
	}
	[HarmonyPatch]
	public class RpcCollectionLoader
	{
		private static GameObject _networkPrefab;

		private static int _networkPrefabInstanceId = -1;

		private static int _networkHandlerHostInstanceId = -1;

		private static NetworkObject _networkHandlerHost;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "OnDestroy")]
		public static void AfterDestroy()
		{
			if ((Object)(object)_networkPrefab != (Object)null)
			{
				RpcCollection component = _networkPrefab.GetComponent<RpcCollection>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				Object.Destroy((Object)(object)_networkPrefab);
				_networkPrefab = null;
				_networkPrefabInstanceId = -1;
			}
			if (!((Object)(object)_networkHandlerHost == (Object)null))
			{
				Object.Destroy((Object)(object)_networkHandlerHost);
				_networkHandlerHost = null;
				_networkPrefabInstanceId = -1;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		public static void SpawnNetworkHandler1()
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			_networkPrefab = NetworkPrefabs.CreateNetworkPrefab("RpcCollectionHandler");
			_networkPrefab.AddComponent<RpcCollection>();
			_networkPrefabInstanceId = ((Object)_networkPrefab).GetInstanceID();
			Object.DontDestroyOnLoad((Object)(object)_networkPrefab);
			if ((NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) && (!((Object)(object)_networkHandlerHost != (Object)null) || !(Object.FindObjectFromInstanceID(_networkHandlerHostInstanceId) != (Object)null)))
			{
				_networkHandlerHost = Object.Instantiate<GameObject>(_networkPrefab, Vector3.zero, Quaternion.identity).GetComponent<NetworkObject>();
				_networkHandlerHost.Spawn(false);
				Object.DontDestroyOnLoad((Object)(object)_networkHandlerHost);
				_networkHandlerHostInstanceId = ((Object)_networkHandlerHost).GetInstanceID();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "OnEnable")]
		public static void SpawnNetworkHandler2()
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_networkPrefab == (Object)null || Object.FindObjectFromInstanceID(_networkPrefabInstanceId) == (Object)null)
			{
				_networkPrefab = NetworkPrefabs.CreateNetworkPrefab("RpcCollectionHandler");
				_networkPrefab.AddComponent<RpcCollection>();
				_networkPrefabInstanceId = ((Object)_networkPrefab).GetInstanceID();
				Object.DontDestroyOnLoad((Object)(object)_networkPrefab);
			}
			if ((NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) && (!((Object)(object)_networkHandlerHost != (Object)null) || !(Object.FindObjectFromInstanceID(_networkHandlerHostInstanceId) != (Object)null)))
			{
				_networkHandlerHost = Object.Instantiate<GameObject>(_networkPrefab, Vector3.zero, Quaternion.identity).GetComponent<NetworkObject>();
				_networkHandlerHost.Spawn(false);
				Object.DontDestroyOnLoad((Object)(object)_networkHandlerHost);
				_networkHandlerHostInstanceId = ((Object)_networkHandlerHost).GetInstanceID();
			}
		}
	}
	[HarmonyPatch(typeof(Smiler))]
	public static class SmilerPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		public static void FixSmiler(Smiler __instance)
		{
			GameObject gameObject = ((Component)((Component)__instance).gameObject.transform.Find("KillBox")).gameObject;
			KillBox component = gameObject.GetComponent<KillBox>();
			Object.Destroy((Object)(object)component);
			gameObject.AddComponent<FixedKillBox>();
		}
	}
	internal static class SoundToolsWrapper
	{
		public static void RestoreAudioClip(string name)
		{
			SoundTool.RestoreAudioClip(name);
		}

		public static void ReplaceAudioClip(string originalName, AudioClip newClip)
		{
			SoundTool.ReplaceAudioClip(originalName, newClip);
		}
	}
	public static class StartOfRoundPatch
	{
		public static void SyncBackroomsConfig()
		{
			if (Plugin.backroomsConfig == null)
			{
				Plugin.ErrorLog("Config not found, please report this!");
			}
			else if (((NetworkBehaviour)RoundManager.Instance).IsHost)
			{
				Plugin.InfoLog("Skipping sync request, since we're the host!");
			}
		}
	}
	public static class UnixTime
	{
		public static long GetCurrentTime()
		{
			return (long)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds;
		}
	}
}