Decompiled source of WitherholdKeep Fix v1.1.0

WitherholdKeepCompatPatch.dll

Decompiled 2 weeks ago
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 BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Photon.Pun;
using REPOLib;
using REPOLib.Modules;
using REPOLib.Objects.Sdk;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Empress")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyInformationalVersion("1.0.5")]
[assembly: AssemblyProduct("WitherholdKeepCompatPatch")]
[assembly: AssemblyTitle("WitherholdKeepCompatPatch")]
[assembly: AssemblyVersion("1.0.5.0")]
[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.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 WitherholdKeepCompatPatch
{
	[BepInPlugin("empress.repo.witherholdkeepcompatpatch", "Empress Witherhold Keep Compat Patch", "1.0.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class WitherholdKeepCompatPatchPlugin : BaseUnityPlugin
	{
		private sealed class WitherholdPrefabBuckets
		{
			public List<GameObject> StartRooms { get; set; } = new List<GameObject>();


			public List<GameObject> Normal1 { get; set; } = new List<GameObject>();


			public List<GameObject> Passage1 { get; set; } = new List<GameObject>();


			public List<GameObject> DeadEnd1 { get; set; } = new List<GameObject>();


			public List<GameObject> Extraction1 { get; set; } = new List<GameObject>();


			public List<GameObject> Normal2 { get; set; } = new List<GameObject>();


			public List<GameObject> Passage2 { get; set; } = new List<GameObject>();


			public List<GameObject> DeadEnd2 { get; set; } = new List<GameObject>();


			public List<GameObject> Extraction2 { get; set; } = new List<GameObject>();


			public List<GameObject> Normal3 { get; set; } = new List<GameObject>();


			public List<GameObject> Passage3 { get; set; } = new List<GameObject>();


			public List<GameObject> DeadEnd3 { get; set; } = new List<GameObject>();


			public List<GameObject> Extraction3 { get; set; } = new List<GameObject>();


			public int TotalModuleCount => Normal1.Count + Passage1.Count + DeadEnd1.Count + Extraction1.Count + Normal2.Count + Passage2.Count + DeadEnd2.Count + Extraction2.Count + Normal3.Count + Passage3.Count + DeadEnd3.Count + Extraction3.Count;
		}

		internal const string PluginGuid = "empress.repo.witherholdkeepcompatpatch";

		internal const string PluginName = "Empress Witherhold Keep Compat Patch";

		internal const string PluginVersion = "1.0.6";

		private const string WitherholdOriginalDllFileName = "WitherholdKeep.dll";

		private const string WitherholdEmbeddedBundleSuffix = ".minecraftbundle";

		private const string WitherholdOriginalPluginGuid = "DirtyGames.WitherholdKeep";

		private const string WitherholdPatchBackupSuffix = ".empress-backup";

		private const string WitherholdLevelName = "Level - Witherhold";

		private const string WitherholdLevelResourcePath = "Witherhold";

		private const string WitherholdValuablePresetName = "Valuables - Minecraft";

		private const float WitherholdLevelPointCheckRadius = 0.5f;

		private const float WitherholdLevelPointRepairRadius = 2f;

		private const float WitherholdLevelPointConnectDistance = 15f;

		private const float WitherholdLevelPointConnectForwardDot = -0.8f;

		private const float WitherholdLevelPointConnectApproachDot = 0.8f;

		private const float WitherholdLevelPointValidationDelay = 0.5f;

		private static readonly string[] WitherholdStartRoomNames = new string[1] { "Module - Minecraft - Start" };

		private static readonly string[] WitherholdNormal1Names = new string[5] { "Module - Rafters - Normal 1", "Module - Rooms - Normal", "Module - Library - Normal", "Module - Altar - Normal", "Module - Blossom - Normal 1" };

		private static readonly string[] WitherholdPassage1Names = new string[4] { "Module - Lava Passage - Passage", "Module - Crypts - Passage", "Module - Lava Bridge - Passage", "Module - Sewer - Passage" };

		private static readonly string[] WitherholdDeadEnd1Names = new string[4] { "Module -Jail - DE", "Module -4 Seasons - DE", "Module -Cathedral - DE", "Module -Portal - DE" };

		private static readonly string[] WitherholdExtraction1Names = new string[2] { "Module - Crypt - Extract", "Module - Graveyard - Extract" };

		private static readonly string[] WitherholdNormal2Names = new string[6] { "Module - Rafters - Normal 1", "Module - Rooms - Normal", "Module - Library - Normal", "Module - Altar - Normal", "Module - Blossom - Normal 1", "Module - Mushroom Factory - Normal" };

		private static readonly string[] WitherholdPassage2Names = new string[5] { "Module - Lava Passage - Passage", "Module - Crypts - Passage", "Module - Lava Bridge - Passage", "Module - Sewer - Passage", "Module - Ice Passage - Passage" };

		private static readonly string[] WitherholdDeadEnd2Names = new string[5] { "Module -Jail - DE", "Module -Portal - DE", "Module -4 Seasons - DE", "Module -Tower - DE", "Module -Cathedral - DE" };

		private static readonly string[] WitherholdExtraction2Names = new string[2] { "Module - Crypt - Extract", "Module - Graveyard - Extract" };

		private static readonly string[] WitherholdNormal3Names = new string[7] { "Module - Rafters - Normal 1", "Module - Rooms - Normal", "Module - Library - Normal", "Module - Altar - Normal", "Module - Blossom - Normal 1", "Module - Library Tomb - Normal", "Module - Mushroom Factory - Normal" };

		private static readonly string[] WitherholdPassage3Names = new string[6] { "Module - Lava Passage - Passage", "Module - Crypts - Passage", "Module - Brick - Passage", "Module - Lava Bridge - Passage", "Module - Sewer - Passage", "Module - Ice Passage - Passage" };

		private static readonly string[] WitherholdDeadEnd3Names = new string[5] { "Module -Jail - DE", "Module -Portal - DE", "Module -4 Seasons - DE", "Module -Cathedral - DE", "Module -Tower - DE" };

		private static readonly string[] WitherholdExtraction3Names = new string[2] { "Module - Crypt - Extract", "Module - Graveyard - Extract" };

		private static readonly string[] WitherholdValuableNames = new string[11]
		{
			"Valuable Slime", "Valuable Minecraft Lever", "Valuable Sushi", "Valuable Gameboy", "Valuable Minecraft Egg", "Valuable Globe - Medium", "Valuable Minecraft Radio", "Valuable Command Block", "Valuable Diamond Ore", "Valuable Minecraft Vase",
			"Valuable Redstone Lamp"
		};

		private readonly Harmony _witherholdHarmony = new Harmony("empress.repo.witherholdkeepcompatpatch");

		private AssetBundle? _witherholdBundle;

		private Level? _witherholdRegisteredLevel;

		private bool _witherholdRepairApplied;

		private bool _witherholdRepairQueued;

		private bool _witherholdLoggedMissingBundle;

		private bool _witherholdLoggedMissingPrefabs;

		private bool _witherholdLoggedDoorMapFallback;

		private bool _witherholdLoggedRepairAttempt;

		private bool _witherholdLoggedRegistrationAttempt;

		private int _witherholdLastLoggedRepairLevelId;

		internal static WitherholdKeepCompatPatchPlugin? Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			_witherholdLastLoggedRepairLevelId = int.MinValue;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			BundleLoader.OnAllBundlesLoaded += WitherholdHandleBundlesLoaded;
			SceneManager.activeSceneChanged += WitherholdOnActiveSceneChanged;
			_witherholdHarmony.PatchAll();
			WitherholdPatchUnityWarningFilter();
			if ((Object)(object)RunManager.instance != (Object)null)
			{
				((MonoBehaviour)this).StartCoroutine(WitherholdRepairWhenReady());
			}
		}

		private void OnDestroy()
		{
			BundleLoader.OnAllBundlesLoaded -= WitherholdHandleBundlesLoaded;
			SceneManager.activeSceneChanged -= WitherholdOnActiveSceneChanged;
			_witherholdHarmony.UnpatchSelf();
			if (Instance == this)
			{
				Instance = null;
			}
		}

		private void WitherholdOnActiveSceneChanged(Scene current, Scene next)
		{
			_witherholdRepairApplied = false;
			_witherholdRepairQueued = false;
			if ((Object)(object)RunManager.instance != (Object)null)
			{
				((MonoBehaviour)this).StartCoroutine(WitherholdRepairWhenReady());
			}
		}

		private void WitherholdHandleBundlesLoaded()
		{
			if (!_witherholdRepairQueued && !_witherholdRepairApplied)
			{
				_witherholdRepairQueued = true;
				((MonoBehaviour)this).StartCoroutine(WitherholdRepairWhenReady());
			}
		}

		private void WitherholdPatchUnityWarningFilter()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			Type type = AccessTools.TypeByName("UnityEngine.DebugLogHandler");
			if (!(type == null))
			{
				MethodInfo methodInfo = AccessTools.Method(type, "LogFormat", new Type[4]
				{
					typeof(LogType),
					typeof(Object),
					typeof(string),
					typeof(object[])
				}, (Type[])null);
				if (methodInfo != null)
				{
					_witherholdHarmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(WitherholdKeepCompatPatchPlugin), "WitherholdSuppressMissingScriptWarningPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo2 = AccessTools.Method(type, "LogFormat", new Type[5]
				{
					typeof(LogType),
					typeof(LogOption),
					typeof(Object),
					typeof(string),
					typeof(object[])
				}, (Type[])null);
				if (methodInfo2 != null)
				{
					_witherholdHarmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(WitherholdKeepCompatPatchPlugin), "WitherholdSuppressMissingScriptWarningPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private IEnumerator WitherholdRepairWhenReady()
		{
			yield return null;
			for (int attempt = 0; attempt < 120; attempt++)
			{
				if (_witherholdRepairApplied)
				{
					break;
				}
				if (WitherholdTryRepairLevel())
				{
					break;
				}
				yield return null;
			}
			_witherholdRepairQueued = false;
		}

		internal bool WitherholdTryRepairCurrentLevel()
		{
			List<Level> list = new List<Level>();
			if ((Object)(object)LevelGenerator.Instance != (Object)null && (Object)(object)LevelGenerator.Instance.Level != (Object)null)
			{
				list.Add(LevelGenerator.Instance.Level);
			}
			if ((Object)(object)RunManager.instance != (Object)null && (Object)(object)RunManager.instance.levelCurrent != (Object)null)
			{
				list.Add(RunManager.instance.levelCurrent);
			}
			return WitherholdTryRepairLevel(list);
		}

		private bool WitherholdTryRepairLevel(IEnumerable<Level>? candidates = null)
		{
			if (_witherholdRepairApplied)
			{
				return true;
			}
			Level val = WitherholdFindLevel(candidates) ?? WitherholdFindLevel(Levels.AllLevels) ?? WitherholdFindLevel(Levels.RegisteredLevels);
			if (val == null)
			{
				val = _witherholdRegisteredLevel;
			}
			if (val == null)
			{
				val = WitherholdEnsureLevelRegistered();
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if (!_witherholdLoggedRepairAttempt)
			{
				_witherholdLoggedRepairAttempt = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Empress Witherhold Keep Compat Patch is rebuilding Level - Witherhold from the original bundle.");
			}
			AssetBundle val2 = WitherholdGetBundle();
			if ((Object)(object)val2 == (Object)null)
			{
				if (!_witherholdLoggedMissingBundle)
				{
					_witherholdLoggedMissingBundle = true;
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Empress Witherhold Keep Compat Patch could not locate the Witherhold Keep bundle.");
				}
				return false;
			}
			_witherholdLoggedMissingBundle = false;
			WitherholdPrefabBuckets witherholdPrefabBuckets = WitherholdCollectPrefabs(val2);
			if (witherholdPrefabBuckets.StartRooms.Count == 0 || witherholdPrefabBuckets.TotalModuleCount == 0)
			{
				if (!_witherholdLoggedMissingPrefabs)
				{
					_witherholdLoggedMissingPrefabs = true;
					((BaseUnityPlugin)this).Logger.LogError((object)"Empress Witherhold Keep Compat Patch could not rebuild the Witherhold Keep prefab lists from the original bundle.");
				}
				return false;
			}
			_witherholdLoggedMissingPrefabs = false;
			WitherholdApplyHideFlags((Object)(object)val2);
			WitherholdApplyHideFlags((Object)(object)val);
			WitherholdEnsureLevelFallbackData(val);
			WitherholdPopulateValuablePreset(val, val2);
			WitherholdRegisterLevelObjects(val);
			val.StartRooms = WitherholdRegisterPrefabs(val, "StartRoom", witherholdPrefabBuckets.StartRooms);
			val.ModulesNormal1 = WitherholdRegisterPrefabs(val, "Normal", witherholdPrefabBuckets.Normal1);
			val.ModulesPassage1 = WitherholdRegisterPrefabs(val, "Passage", witherholdPrefabBuckets.Passage1);
			val.ModulesDeadEnd1 = WitherholdRegisterPrefabs(val, "DeadEnd", witherholdPrefabBuckets.DeadEnd1);
			val.ModulesExtraction1 = WitherholdRegisterPrefabs(val, "Extraction", witherholdPrefabBuckets.Extraction1);
			val.ModulesNormal2 = WitherholdRegisterPrefabs(val, "Normal", witherholdPrefabBuckets.Normal2);
			val.ModulesPassage2 = WitherholdRegisterPrefabs(val, "Passage", witherholdPrefabBuckets.Passage2);
			val.ModulesDeadEnd2 = WitherholdRegisterPrefabs(val, "DeadEnd", witherholdPrefabBuckets.DeadEnd2);
			val.ModulesExtraction2 = WitherholdRegisterPrefabs(val, "Extraction", witherholdPrefabBuckets.Extraction2);
			val.ModulesNormal3 = WitherholdRegisterPrefabs(val, "Normal", witherholdPrefabBuckets.Normal3);
			val.ModulesPassage3 = WitherholdRegisterPrefabs(val, "Passage", witherholdPrefabBuckets.Passage3);
			val.ModulesDeadEnd3 = WitherholdRegisterPrefabs(val, "DeadEnd", witherholdPrefabBuckets.DeadEnd3);
			val.ModulesExtraction3 = WitherholdRegisterPrefabs(val, "Extraction", witherholdPrefabBuckets.Extraction3);
			_witherholdRepairApplied = WitherholdCountValidPrefabRefs(val.StartRooms) > 0 && WitherholdCountValidModules(val) > 0;
			if (_witherholdRepairApplied && _witherholdLastLoggedRepairLevelId != ((Object)val).GetInstanceID())
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Empress Witherhold Keep Compat Patch repaired {((Object)val).name} with {WitherholdCountValidPrefabRefs(val.StartRooms)} start rooms and {WitherholdCountValidModules(val)} modules.");
				_witherholdLastLoggedRepairLevelId = ((Object)val).GetInstanceID();
			}
			return _witherholdRepairApplied;
		}

		private Level? WitherholdEnsureLevelRegistered()
		{
			Level val = WitherholdFindLevel(Levels.AllLevels) ?? WitherholdFindLevel(Levels.RegisteredLevels) ?? _witherholdRegisteredLevel;
			if ((Object)(object)val != (Object)null)
			{
				_witherholdRegisteredLevel = val;
				return val;
			}
			if (!_witherholdLoggedRegistrationAttempt)
			{
				_witherholdLoggedRegistrationAttempt = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Empress Witherhold Keep Compat Patch is registering Level - Witherhold with current REPOLib.");
			}
			AssetBundle val2 = WitherholdGetBundle();
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			Level val3 = ((IEnumerable<Level>)val2.LoadAllAssets<Level>()).FirstOrDefault((Func<Level, bool>)WitherholdIsWitherholdLevel);
			if ((Object)(object)val3 == (Object)null)
			{
				return null;
			}
			WitherholdPrefabBuckets witherholdPrefabBuckets = WitherholdCollectPrefabs(val2);
			if (witherholdPrefabBuckets.StartRooms.Count == 0 || witherholdPrefabBuckets.TotalModuleCount == 0)
			{
				return null;
			}
			WitherholdApplyHideFlags((Object)(object)val2);
			WitherholdApplyHideFlags((Object)(object)val3);
			WitherholdEnsureLevelFallbackData(val3);
			WitherholdSanitizeValuablePresetForRegistration(val3, val2);
			WitherholdPrepareLevelRegistration(val3, witherholdPrefabBuckets);
			LevelContent val4 = ScriptableObject.CreateInstance<LevelContent>();
			WitherholdApplyHideFlags((Object)(object)val4);
			((Object)val4).name = ((Object)val3).name + " Content";
			AccessTools.Field(typeof(LevelContent), "_level")?.SetValue(val4, val3);
			AccessTools.Field(typeof(LevelContent), "_connectObject")?.SetValue(val4, val3.ConnectObject);
			AccessTools.Field(typeof(LevelContent), "_blockObject")?.SetValue(val4, val3.BlockObject);
			AccessTools.Field(typeof(LevelContent), "_startRooms")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.StartRooms));
			AccessTools.Field(typeof(LevelContent), "_modulesNormal1")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.Normal1));
			AccessTools.Field(typeof(LevelContent), "_modulesPassage1")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.Passage1));
			AccessTools.Field(typeof(LevelContent), "_modulesDeadEnd1")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.DeadEnd1));
			AccessTools.Field(typeof(LevelContent), "_modulesExtraction1")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.Extraction1));
			AccessTools.Field(typeof(LevelContent), "_modulesNormal2")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.Normal2));
			AccessTools.Field(typeof(LevelContent), "_modulesPassage2")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.Passage2));
			AccessTools.Field(typeof(LevelContent), "_modulesDeadEnd2")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.DeadEnd2));
			AccessTools.Field(typeof(LevelContent), "_modulesExtraction2")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.Extraction2));
			AccessTools.Field(typeof(LevelContent), "_modulesNormal3")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.Normal3));
			AccessTools.Field(typeof(LevelContent), "_modulesPassage3")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.Passage3));
			AccessTools.Field(typeof(LevelContent), "_modulesDeadEnd3")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.DeadEnd3));
			AccessTools.Field(typeof(LevelContent), "_modulesExtraction3")?.SetValue(val4, new List<GameObject>(witherholdPrefabBuckets.Extraction3));
			Levels.RegisterLevel(val4);
			WitherholdPopulateValuablePreset(val3, val2);
			_witherholdRegisteredLevel = WitherholdFindLevel(Levels.AllLevels) ?? WitherholdFindLevel(Levels.RegisteredLevels) ?? val3;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Empress Witherhold Keep Compat Patch registered Level - Witherhold with current REPOLib.");
			return _witherholdRegisteredLevel;
		}

		private static Level? WitherholdFindLevel(IEnumerable<Level>? candidates)
		{
			if (candidates == null)
			{
				return null;
			}
			foreach (Level candidate in candidates)
			{
				if (WitherholdIsWitherholdLevel(candidate))
				{
					return candidate;
				}
			}
			return null;
		}

		private AssetBundle? WitherholdGetBundle()
		{
			if ((Object)(object)_witherholdBundle != (Object)null)
			{
				return _witherholdBundle;
			}
			foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles())
			{
				if (WitherholdBundleMatches(allLoadedAssetBundle))
				{
					_witherholdBundle = allLoadedAssetBundle;
					return _witherholdBundle;
				}
			}
			_witherholdBundle = WitherholdLoadEmbeddedBundleFromOriginalPlugin();
			if ((Object)(object)_witherholdBundle != (Object)null)
			{
				return _witherholdBundle;
			}
			foreach (AssetBundle allLoadedAssetBundle2 in AssetBundle.GetAllLoadedAssetBundles())
			{
				if (WitherholdBundleMatches(allLoadedAssetBundle2))
				{
					_witherholdBundle = allLoadedAssetBundle2;
					return _witherholdBundle;
				}
			}
			return _witherholdBundle;
		}

		private static bool WitherholdBundleMatches(AssetBundle? bundle)
		{
			if ((Object)(object)bundle == (Object)null)
			{
				return false;
			}
			try
			{
				if (!string.IsNullOrWhiteSpace(((Object)bundle).name) && (((Object)bundle).name.IndexOf("witherhold", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)bundle).name.IndexOf("minecraftbundle", StringComparison.OrdinalIgnoreCase) >= 0))
				{
					return true;
				}
			}
			catch
			{
			}
			try
			{
				if (bundle.GetAllAssetNames().Any((string assetName) => assetName.IndexOf("level - witherhold.asset", StringComparison.OrdinalIgnoreCase) >= 0 || assetName.IndexOf("valuables - minecraft.asset", StringComparison.OrdinalIgnoreCase) >= 0))
				{
					return true;
				}
			}
			catch
			{
			}
			try
			{
				Level[] array = bundle.LoadAllAssets<Level>();
				for (int i = 0; i < array.Length; i++)
				{
					if (WitherholdIsWitherholdLevel(array[i]))
					{
						return true;
					}
				}
			}
			catch
			{
			}
			try
			{
				GameObject[] array2 = bundle.LoadAllAssets<GameObject>();
				foreach (GameObject val in array2)
				{
					if (!((Object)(object)val == (Object)null) && (((Object)val).name.StartsWith("Module - Minecraft - Start", StringComparison.OrdinalIgnoreCase) || ((Object)val).name.StartsWith("Module - Rafters - Normal 1", StringComparison.OrdinalIgnoreCase) || ((Object)val).name.StartsWith("Module - Crypt - Extract", StringComparison.OrdinalIgnoreCase)))
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private bool TryPatchInstalledWitherholdPlugin()
		{
			bool flag = false;
			foreach (string item in Directory.GetFiles(Paths.PluginPath, "WitherholdKeep.dll", SearchOption.AllDirectories).Distinct<string>(StringComparer.OrdinalIgnoreCase))
			{
				flag |= TryPatchInstalledWitherholdPlugin(item);
			}
			return flag;
		}

		private bool TryPatchInstalledWitherholdPlugin(string dllPath)
		{
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (string.IsNullOrWhiteSpace(dllPath) || !File.Exists(dllPath))
				{
					return false;
				}
				string location = typeof(BundleLoader).Assembly.Location;
				if (string.IsNullOrWhiteSpace(location) || !File.Exists(location))
				{
					return false;
				}
				using MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(dllPath), writable: false);
				AssemblyDefinition val = AssemblyDefinition.ReadAssembly((Stream)memoryStream);
				ModuleDefinition mainModule = val.MainModule;
				TypeDefinition val2 = ((IEnumerable<TypeDefinition>)mainModule.Types).FirstOrDefault((Func<TypeDefinition, bool>)((TypeDefinition type) => ((MemberReference)type).FullName == "WitherholdKeep.WitherholdKeep"));
				if (val2 == null)
				{
					return false;
				}
				if (!((IEnumerable<CustomAttribute>)val2.CustomAttributes).Any(delegate(CustomAttribute attribute)
				{
					//IL_0036: Unknown result type (might be due to invalid IL or missing references)
					//IL_003b: Unknown result type (might be due to invalid IL or missing references)
					if (((MemberReference)attribute.AttributeType).FullName == typeof(BepInPlugin).FullName && attribute.ConstructorArguments.Count >= 1)
					{
						CustomAttributeArgument val9 = attribute.ConstructorArguments[0];
						return string.Equals(((CustomAttributeArgument)(ref val9)).Value as string, "DirtyGames.WitherholdKeep", StringComparison.Ordinal);
					}
					return false;
				}))
				{
					return false;
				}
				bool flag = false;
				MethodDefinition val3 = ((IEnumerable<MethodDefinition>)val2.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition method) => ((MemberReference)method).Name == "Awake" && method.HasBody));
				if (val3 != null)
				{
					Instruction val4 = ((IEnumerable<Instruction>)val3.Body.Instructions).FirstOrDefault((Func<Instruction, bool>)delegate(Instruction instruction)
					{
						//IL_0001: Unknown result type (might be due to invalid IL or missing references)
						//IL_0006: Unknown result type (might be due to invalid IL or missing references)
						if (instruction.OpCode == OpCodes.Call)
						{
							object operand2 = instruction.Operand;
							MethodReference val8 = (MethodReference)((operand2 is MethodReference) ? operand2 : null);
							if (val8 != null && ((MemberReference)((MemberReference)val8).DeclaringType).FullName == "REPOLib.Modules.Valuables" && ((MemberReference)val8).Name == "RegisterValuable" && val8.Parameters.Count == 1 && ((MemberReference)((ParameterReference)val8.Parameters[0]).ParameterType).FullName == typeof(GameObject).FullName)
							{
								return ((MemberReference)val8.ReturnType).FullName == typeof(void).FullName;
							}
						}
						return false;
					});
					if (val4 != null)
					{
						using MemoryStream memoryStream2 = new MemoryStream(File.ReadAllBytes(location), writable: false);
						MethodDefinition val5 = ((IEnumerable<MethodDefinition>)((IEnumerable<TypeDefinition>)AssemblyDefinition.ReadAssembly((Stream)memoryStream2).MainModule.Types).First((TypeDefinition type) => ((MemberReference)type).FullName == "REPOLib.Modules.Valuables").Methods).First((MethodDefinition method) => ((MemberReference)method).Name == "RegisterValuable" && ((MethodReference)method).Parameters.Count == 1 && ((MemberReference)((ParameterReference)((MethodReference)method).Parameters[0]).ParameterType).FullName == typeof(GameObject).FullName && ((MemberReference)((MethodReference)method).ReturnType).FullName != typeof(void).FullName);
						val4.Operand = mainModule.ImportReference((MethodReference)(object)val5);
						if (val4.Next == null || val4.Next.OpCode != OpCodes.Pop)
						{
							val3.Body.GetILProcessor().InsertAfter(val4, Instruction.Create(OpCodes.Pop));
						}
						flag = true;
					}
				}
				TypeDefinition? obj = ((IEnumerable<TypeDefinition>)mainModule.Types).FirstOrDefault((Func<TypeDefinition, bool>)((TypeDefinition type) => ((MemberReference)type).FullName == "WitherholdKeep.LevelGeneratorStartPatch"));
				MethodDefinition? obj2 = ((obj != null) ? ((IEnumerable<MethodDefinition>)obj.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition method) => ((MemberReference)method).Name == "Prefix" && method.HasBody)) : null);
				Instruction val6 = ((obj2 != null) ? ((IEnumerable<Instruction>)obj2.Body.Instructions).FirstOrDefault((Func<Instruction, bool>)delegate(Instruction instruction)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					if (instruction.OpCode == OpCodes.Call)
					{
						object operand = instruction.Operand;
						MethodReference val7 = (MethodReference)((operand is MethodReference) ? operand : null);
						if (val7 != null && ((MemberReference)((MemberReference)val7).DeclaringType).FullName == "REPOLib.Modules.Levels" && ((MemberReference)val7).Name == "RegisterLevel" && val7.Parameters.Count == 1 && ((MemberReference)((ParameterReference)val7.Parameters[0]).ParameterType).FullName == typeof(Level).FullName)
						{
							return ((MemberReference)val7.ReturnType).FullName == typeof(void).FullName;
						}
					}
					return false;
				}) : null);
				if (val6 != null)
				{
					val6.OpCode = OpCodes.Pop;
					val6.Operand = null;
					flag = true;
				}
				if (!flag)
				{
					return false;
				}
				string text = dllPath + ".empress-patched";
				string text2 = dllPath + ".empress-backup";
				val.Write(text);
				if (!File.Exists(text2))
				{
					File.Copy(dllPath, text2);
				}
				File.Copy(text, dllPath, overwrite: true);
				File.Delete(text);
				return true;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Empress Witherhold Keep Compat Patch could not patch '" + dllPath + "': " + ex.Message));
				return false;
			}
		}

		private static AssetBundle? WitherholdLoadEmbeddedBundleFromOriginalPlugin()
		{
			try
			{
				string text = Directory.GetFiles(Paths.PluginPath, "WitherholdKeep.dll", SearchOption.AllDirectories).FirstOrDefault();
				if (string.IsNullOrWhiteSpace(text))
				{
					return null;
				}
				Assembly assembly = Assembly.LoadFile(text);
				string text2 = assembly.GetManifestResourceNames().FirstOrDefault((string name) => name.EndsWith(".minecraftbundle", StringComparison.OrdinalIgnoreCase));
				if (string.IsNullOrWhiteSpace(text2))
				{
					return null;
				}
				using Stream stream = assembly.GetManifestResourceStream(text2);
				if (stream == null)
				{
					return null;
				}
				byte[] array = new byte[stream.Length];
				int i;
				int num;
				for (i = 0; i < array.Length; i += num)
				{
					num = stream.Read(array, i, array.Length - i);
					if (num <= 0)
					{
						break;
					}
				}
				if (i != array.Length)
				{
					return null;
				}
				return AssetBundle.LoadFromMemory(array);
			}
			catch
			{
				return null;
			}
		}

		private static WitherholdPrefabBuckets WitherholdCollectPrefabs(AssetBundle bundle)
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);
			StartRoom[] array = bundle.LoadAllAssets<StartRoom>();
			foreach (StartRoom val in array)
			{
				WitherholdAddAssetByName(dictionary, ((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null);
			}
			Module[] array2 = bundle.LoadAllAssets<Module>();
			foreach (Module val2 in array2)
			{
				WitherholdAddAssetByName(dictionary, ((Object)(object)val2 != (Object)null) ? ((Component)val2).gameObject : null);
			}
			GameObject[] array3 = bundle.LoadAllAssets<GameObject>();
			foreach (GameObject prefab in array3)
			{
				WitherholdAddAssetByName(dictionary, prefab);
			}
			if (!dictionary.ContainsKey("Module - Minecraft - Start") || !dictionary.ContainsKey("Module - Rafters - Normal 1"))
			{
				array = Resources.FindObjectsOfTypeAll<StartRoom>();
				Scene scene;
				foreach (StartRoom val3 in array)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						scene = ((Component)val3).gameObject.scene;
						if (!((Scene)(ref scene)).IsValid())
						{
							WitherholdAddAssetByName(dictionary, ((Component)val3).gameObject);
						}
					}
				}
				array2 = Resources.FindObjectsOfTypeAll<Module>();
				foreach (Module val4 in array2)
				{
					if (!((Object)(object)val4 == (Object)null))
					{
						scene = ((Component)val4).gameObject.scene;
						if (!((Scene)(ref scene)).IsValid())
						{
							WitherholdAddAssetByName(dictionary, ((Component)val4).gameObject);
						}
					}
				}
				array3 = Resources.FindObjectsOfTypeAll<GameObject>();
				foreach (GameObject val5 in array3)
				{
					if (!((Object)(object)val5 == (Object)null))
					{
						scene = val5.scene;
						if (!((Scene)(ref scene)).IsValid())
						{
							WitherholdAddAssetByName(dictionary, val5);
						}
					}
				}
			}
			return new WitherholdPrefabBuckets
			{
				StartRooms = WitherholdResolvePrefabs(dictionary, WitherholdStartRoomNames),
				Normal1 = WitherholdResolvePrefabs(dictionary, WitherholdNormal1Names),
				Passage1 = WitherholdResolvePrefabs(dictionary, WitherholdPassage1Names),
				DeadEnd1 = WitherholdResolvePrefabs(dictionary, WitherholdDeadEnd1Names),
				Extraction1 = WitherholdResolvePrefabs(dictionary, WitherholdExtraction1Names),
				Normal2 = WitherholdResolvePrefabs(dictionary, WitherholdNormal2Names),
				Passage2 = WitherholdResolvePrefabs(dictionary, WitherholdPassage2Names),
				DeadEnd2 = WitherholdResolvePrefabs(dictionary, WitherholdDeadEnd2Names),
				Extraction2 = WitherholdResolvePrefabs(dictionary, WitherholdExtraction2Names),
				Normal3 = WitherholdResolvePrefabs(dictionary, WitherholdNormal3Names),
				Passage3 = WitherholdResolvePrefabs(dictionary, WitherholdPassage3Names),
				DeadEnd3 = WitherholdResolvePrefabs(dictionary, WitherholdDeadEnd3Names),
				Extraction3 = WitherholdResolvePrefabs(dictionary, WitherholdExtraction3Names)
			};
		}

		private static void WitherholdAddAssetByName(IDictionary<string, GameObject> prefabsByName, GameObject? prefab)
		{
			if (!((Object)(object)prefab == (Object)null) && !string.IsNullOrWhiteSpace(((Object)prefab).name) && !prefabsByName.ContainsKey(((Object)prefab).name))
			{
				prefabsByName[((Object)prefab).name] = prefab;
			}
		}

		private static List<GameObject> WitherholdResolvePrefabs(IReadOnlyDictionary<string, GameObject> prefabsByName, IEnumerable<string> names)
		{
			List<GameObject> list = new List<GameObject>();
			foreach (string name in names)
			{
				if (prefabsByName.TryGetValue(name, out GameObject value))
				{
					list.Add(value);
				}
			}
			return list;
		}

		private static void WitherholdRegisterLevelObjects(Level level)
		{
			if ((Object)(object)level.ConnectObject != (Object)null)
			{
				WitherholdRegisterNetworkPrefab("Level/" + (level.ResourcePath ?? "Witherhold") + "/Other/" + ((Object)level.ConnectObject).name, level.ConnectObject);
			}
			if ((Object)(object)level.BlockObject != (Object)null)
			{
				WitherholdRegisterNetworkPrefab("Level/" + (level.ResourcePath ?? "Witherhold") + "/Other/" + ((Object)level.BlockObject).name, level.BlockObject);
			}
		}

		private static void WitherholdPrepareLevelRegistration(Level level, WitherholdPrefabBuckets prefabs)
		{
			if ((Object)(object)level.ConnectObject != (Object)null)
			{
				WitherholdPreparePrefab(level.ConnectObject);
			}
			if ((Object)(object)level.BlockObject != (Object)null)
			{
				WitherholdPreparePrefab(level.BlockObject);
			}
			foreach (GameObject item in (from prefab in prefabs.StartRooms.Concat(prefabs.Normal1).Concat(prefabs.Passage1).Concat(prefabs.DeadEnd1)
					.Concat(prefabs.Extraction1)
					.Concat(prefabs.Normal2)
					.Concat(prefabs.Passage2)
					.Concat(prefabs.DeadEnd2)
					.Concat(prefabs.Extraction2)
					.Concat(prefabs.Normal3)
					.Concat(prefabs.Passage3)
					.Concat(prefabs.DeadEnd3)
					.Concat(prefabs.Extraction3)
				where (Object)(object)prefab != (Object)null
				select prefab).Distinct())
			{
				WitherholdPreparePrefab(item);
			}
		}

		private static void WitherholdSanitizeValuablePresetForRegistration(Level level, AssetBundle bundle)
		{
			LevelValuables val = WitherholdGetValuablePreset(level, bundle);
			if (!((Object)(object)val == (Object)null))
			{
				WitherholdApplyHideFlags((Object)(object)val);
				WitherholdClearValuableRefs(val.tiny);
				WitherholdClearValuableRefs(val.small);
				WitherholdClearValuableRefs(val.medium);
				WitherholdClearValuableRefs(val.big);
				WitherholdClearValuableRefs(val.wide);
				WitherholdClearValuableRefs(val.tall);
				WitherholdClearValuableRefs(val.veryTall);
				if (level.ValuablePresets == null)
				{
					level.ValuablePresets = new List<LevelValuables>();
				}
				if (!level.ValuablePresets.Contains(val))
				{
					level.ValuablePresets.Add(val);
				}
			}
		}

		private static void WitherholdPopulateValuablePreset(Level level, AssetBundle bundle)
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			LevelValuables val = WitherholdGetValuablePreset(level, bundle);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			string[] witherholdValuableNames = WitherholdValuableNames;
			ValuableObject val3 = default(ValuableObject);
			foreach (string text in witherholdValuableNames)
			{
				GameObject val2 = bundle.LoadAsset<GameObject>(text + ".prefab");
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				WitherholdPreparePrefab(val2);
				string key = "Valuables/" + ((Object)val2).name;
				if (!NetworkPrefabs.PrefabRefs.TryGetValue(key, out var value) || value == null)
				{
					value = Valuables.RegisterValuable(val2, new List<string> { "Valuables - Minecraft" });
					if (value == null)
					{
						NetworkPrefabs.PrefabRefs.TryGetValue(key, out value);
					}
				}
				if (value != null && value.IsValid() && val2.TryGetComponent<ValuableObject>(ref val3) && WitherholdTryGetValuableList(val, val3.volumeType, out List<PrefabRef> list) && !list.Contains(value))
				{
					list.Add(value);
				}
			}
			if (!level.ValuablePresets.Contains(val))
			{
				level.ValuablePresets.Add(val);
			}
		}

		private static LevelValuables? WitherholdGetValuablePreset(Level level, AssetBundle bundle)
		{
			if (level.ValuablePresets == null)
			{
				level.ValuablePresets = new List<LevelValuables>();
			}
			return ((IEnumerable<LevelValuables>)level.ValuablePresets).FirstOrDefault((Func<LevelValuables, bool>)((LevelValuables candidate) => (Object)(object)candidate != (Object)null && string.Equals(((Object)candidate).name, "Valuables - Minecraft", StringComparison.OrdinalIgnoreCase))) ?? ((IEnumerable<LevelValuables>)bundle.LoadAllAssets<LevelValuables>()).FirstOrDefault((Func<LevelValuables, bool>)((LevelValuables candidate) => (Object)(object)candidate != (Object)null && string.Equals(((Object)candidate).name, "Valuables - Minecraft", StringComparison.OrdinalIgnoreCase)));
		}

		private static void WitherholdClearValuableRefs(List<PrefabRef>? prefabRefs)
		{
			prefabRefs?.Clear();
		}

		private static bool WitherholdTryGetValuableList(LevelValuables preset, Type volumeType, out List<PrefabRef> list)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected I4, but got Unknown
			switch ((int)volumeType)
			{
			case 0:
				list = preset.tiny;
				return list != null;
			case 1:
				list = preset.small;
				return list != null;
			case 2:
				list = preset.medium;
				return list != null;
			case 3:
				list = preset.big;
				return list != null;
			case 4:
				list = preset.wide;
				return list != null;
			case 5:
				list = preset.tall;
				return list != null;
			case 6:
				list = preset.veryTall;
				return list != null;
			default:
				list = null;
				return false;
			}
		}

		private static List<PrefabRef> WitherholdRegisterPrefabs(Level level, string moduleTypeName, IEnumerable<GameObject> prefabs)
		{
			List<PrefabRef> list = new List<PrefabRef>();
			foreach (GameObject prefab in prefabs)
			{
				PrefabRef val = WitherholdRegisterNetworkPrefab("Level/" + ((Object)level).name + "/" + moduleTypeName + "/" + ((Object)prefab).name, prefab);
				if (val != null)
				{
					list.Add(val);
				}
			}
			return list;
		}

		private static PrefabRef? WitherholdRegisterNetworkPrefab(string prefabId, GameObject prefab)
		{
			PrefabRef val = WitherholdGetRegisteredPrefabRef(prefabId, prefab);
			if (val != null)
			{
				return val;
			}
			WitherholdPreparePrefab(prefab);
			Utilities.FixAudioMixerGroups(prefab);
			return NetworkPrefabs.RegisterNetworkPrefab(prefabId, prefab);
		}

		private static PrefabRef? WitherholdGetRegisteredPrefabRef(string prefabId, GameObject prefab)
		{
			if (!NetworkPrefabs.PrefabRefs.TryGetValue(prefabId, out var value) || value == null)
			{
				return null;
			}
			if ((Object)(object)value.Prefab == (Object)null || (Object)(object)value.Prefab == (Object)(object)prefab)
			{
				return value;
			}
			return null;
		}

		private static void WitherholdPreparePrefab(GameObject prefab)
		{
			WitherholdApplyHideFlags((Object)(object)prefab);
			WitherholdAssignFallbackAudioMixerGroups(prefab);
			WitherholdAssignFallbackPhysAttributes(prefab);
			WitherholdAssignFallbackHingeData(prefab);
			WitherholdAssignFallbackChargingStationData(prefab);
		}

		private static void WitherholdAssignFallbackAudioMixerGroups(GameObject prefab)
		{
			AudioMixerGroup val = WitherholdGetFallbackAudioMixerGroup();
			if ((Object)(object)prefab == (Object)null || (Object)(object)val == (Object)null)
			{
				return;
			}
			AudioSource[] componentsInChildren = prefab.GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.outputAudioMixerGroup != (Object)null))
				{
					val2.outputAudioMixerGroup = val;
				}
			}
		}

		private static void WitherholdAssignFallbackPhysAttributes(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			NotValuableObject[] componentsInChildren = prefab.GetComponentsInChildren<NotValuableObject>(true);
			foreach (NotValuableObject val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.physAttributePreset != (Object)null))
				{
					Rigidbody component = ((Component)val).GetComponent<Rigidbody>();
					float mass = (((Object)(object)component != (Object)null && component.mass > 0f) ? component.mass : 1f);
					val.physAttributePreset = WitherholdCreateFallbackPhysAttribute(mass);
				}
			}
		}

		private static void WitherholdAssignFallbackHingeData(GameObject prefab)
		{
			if (!((Object)(object)prefab == (Object)null))
			{
				PhysGrabHinge[] componentsInChildren = prefab.GetComponentsInChildren<PhysGrabHinge>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					WitherholdEnsurePhysGrabHingeCompatibility(componentsInChildren[i]);
				}
			}
		}

		private static void WitherholdAssignFallbackChargingStationData(GameObject prefab)
		{
			if (!((Object)(object)prefab == (Object)null))
			{
				ChargingStation[] componentsInChildren = prefab.GetComponentsInChildren<ChargingStation>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					WitherholdEnsureChargingStationCompatibility(componentsInChildren[i]);
				}
			}
		}

		internal static void WitherholdEnsureChargingStationCompatibility(ChargingStation? chargingStation)
		{
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			//IL_070b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)chargingStation == (Object)null)
			{
				return;
			}
			ChargingStation val = WitherholdFindFallbackChargingStationTemplate();
			Transform templateRoot = (((Object)(object)val != (Object)null) ? ((Component)val).transform : null);
			Transform transform = ((Component)chargingStation).transform;
			int num = Mathf.Max(WitherholdGetChargingStationField(chargingStation, "maxCrystals", 10), ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField(val, "maxCrystals", 10) : 10);
			WitherholdSetChargingStationField(chargingStation, "maxCrystals", num);
			int num2 = Mathf.Max(WitherholdGetChargingStationField(chargingStation, "energyPerCrystal", 10), ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField(val, "energyPerCrystal", 10) : 10);
			WitherholdSetChargingStationField(chargingStation, "energyPerCrystal", num2);
			int num3 = Mathf.Max(WitherholdGetChargingStationField(chargingStation, "chargeSegments", 40), ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField(val, "chargeSegments", 40) : 40);
			WitherholdSetChargingStationField(chargingStation, "chargeSegments", num3);
			List<ItemBattery> value = WitherholdGetChargingStationField<List<ItemBattery>>(chargingStation, "itemsCharging") ?? new List<ItemBattery>();
			WitherholdSetChargingStationField(chargingStation, "itemsCharging", value);
			List<Transform> list = WitherholdGetChargingStationField<List<Transform>>(chargingStation, "crystals") ?? new List<Transform>();
			Scene scene = ((Component)chargingStation).gameObject.scene;
			if (!((Scene)(ref scene)).IsValid())
			{
				list.Clear();
			}
			else
			{
				list.RemoveAll((Transform crystal) => (Object)(object)crystal == (Object)null);
			}
			WitherholdSetChargingStationField(chargingStation, "crystals", list);
			PhotonView value2 = WitherholdGetChargingStationField<PhotonView>(chargingStation, "photonView") ?? ((Component)chargingStation).GetComponent<PhotonView>();
			WitherholdSetChargingStationField(chargingStation, "photonView", value2);
			GameObject value3 = WitherholdMapGameObject(transform, templateRoot, ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<GameObject>(val, "meshObject") : null) ?? WitherholdGetChargingStationField<GameObject>(chargingStation, "meshObject") ?? WitherholdFindBestRendererGameObject(transform) ?? WitherholdCreateFallbackMeshObject(transform);
			WitherholdSetChargingStationField(chargingStation, "meshObject", value3);
			Transform value4 = WitherholdMapTransform(transform, templateRoot, ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<Transform>(val, "chargeBar") : null) ?? WitherholdGetChargingStationField<Transform>(chargingStation, "chargeBar") ?? WitherholdFindChildByExactName(transform, "Charge") ?? WitherholdCreateFallbackAnchor(transform, "Charge", new Vector3(0f, 0.38f, 0.12f), new Vector3(0.75f, 0.12f, 0.12f));
			WitherholdSetChargingStationField(chargingStation, "chargeBar", value4);
			Transform value5 = WitherholdMapTransform(transform, templateRoot, ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<Transform>(val, "chargeArea") : null) ?? WitherholdGetChargingStationField<Transform>(chargingStation, "chargeArea") ?? WitherholdFindChildByExactName(transform, "Charge Area") ?? WitherholdCreateFallbackAnchor(transform, "Charge Area", new Vector3(0f, 0.65f, 0.7f), new Vector3(1.1f, 1.1f, 1.1f));
			WitherholdSetChargingStationField(chargingStation, "chargeArea", value5);
			Transform value6 = WitherholdMapTransform(transform, templateRoot, ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<Transform>(val, "lockedTransform") : null) ?? WitherholdGetChargingStationField<Transform>(chargingStation, "lockedTransform") ?? WitherholdFindChildByExactName(transform, "Locked");
			WitherholdSetChargingStationField(chargingStation, "lockedTransform", value6);
			Transform value7 = WitherholdMapTransform(transform, templateRoot, ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<Transform>(val, "crystalCylinder") : null) ?? WitherholdGetChargingStationField<Transform>(chargingStation, "crystalCylinder") ?? WitherholdFindChildByExactName(transform, "Crystal Cylinder") ?? WitherholdFindChildContaining(transform, "crystal") ?? WitherholdCreateFallbackCrystalCylinder(transform, num);
			WitherholdSetChargingStationField(chargingStation, "crystalCylinder", value7);
			object obj = WitherholdMapComponent<Light>(transform, templateRoot, ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<Light>(val, "light1") : null);
			if (obj == null)
			{
				obj = WitherholdGetChargingStationField<Light>(chargingStation, "light1");
				if (obj == null)
				{
					Transform? obj2 = WitherholdFindChildByExactName(transform, "Light1");
					obj = ((obj2 != null) ? ((Component)obj2).GetComponent<Light>() : null) ?? WitherholdCreateFallbackLight(transform, "Light1", new Vector3(-0.16f, 0.62f, 0.16f), 0.8f);
				}
			}
			Light value8 = (Light)obj;
			WitherholdSetChargingStationField(chargingStation, "light1", value8);
			object obj3 = WitherholdMapComponent<Light>(transform, templateRoot, ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<Light>(val, "light2") : null);
			if (obj3 == null)
			{
				obj3 = WitherholdGetChargingStationField<Light>(chargingStation, "light2");
				if (obj3 == null)
				{
					Transform? obj4 = WitherholdFindChildByExactName(transform, "Light2");
					obj3 = ((obj4 != null) ? ((Component)obj4).GetComponent<Light>() : null) ?? WitherholdCreateFallbackLight(transform, "Light2", new Vector3(0.16f, 0.62f, 0.16f), 0.8f);
				}
			}
			Light value9 = (Light)obj3;
			WitherholdSetChargingStationField(chargingStation, "light2", value9);
			object obj5 = WitherholdMapGameObject(transform, templateRoot, ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<GameObject>(val, "subtleLight") : null);
			if (obj5 == null)
			{
				obj5 = WitherholdGetChargingStationField<GameObject>(chargingStation, "subtleLight");
				if (obj5 == null)
				{
					Transform? obj6 = WitherholdFindChildByExactName(transform, "Subtle Light");
					obj5 = ((obj6 != null) ? ((Component)obj6).gameObject : null) ?? ((Component)WitherholdCreateFallbackSubtleLight(transform)).gameObject;
				}
			}
			GameObject val2 = (GameObject)obj5;
			WitherholdSetChargingStationField(chargingStation, "subtleLight", val2);
			Light value10 = WitherholdMapComponent<Light>(transform, templateRoot, ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<Light>(val, "barLight") : null) ?? WitherholdGetChargingStationField<Light>(chargingStation, "barLight") ?? ((val2 != null) ? val2.GetComponent<Light>() : null) ?? WitherholdCreateFallbackLight(transform, "Bar Light", new Vector3(0f, 0.48f, 0.08f), 0.8f);
			WitherholdSetChargingStationField(chargingStation, "barLight", value10);
			object obj7 = WitherholdMapComponent<ParticleSystem>(transform, templateRoot, ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<ParticleSystem>(val, "lightParticle") : null);
			if (obj7 == null)
			{
				obj7 = WitherholdGetChargingStationField<ParticleSystem>(chargingStation, "lightParticle");
				if (obj7 == null)
				{
					Transform? obj8 = WitherholdFindChildByExactName(transform, "Light Particle");
					obj7 = ((obj8 != null) ? ((Component)obj8).GetComponent<ParticleSystem>() : null) ?? WitherholdCreateFallbackParticleSystem(transform, "Light Particle");
				}
			}
			ParticleSystem value11 = (ParticleSystem)obj7;
			WitherholdSetChargingStationField(chargingStation, "lightParticle", value11);
			object obj9 = WitherholdMapComponent<ParticleSystem>(transform, templateRoot, ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<ParticleSystem>(val, "fireflyParticles") : null);
			if (obj9 == null)
			{
				obj9 = WitherholdGetChargingStationField<ParticleSystem>(chargingStation, "fireflyParticles");
				if (obj9 == null)
				{
					Transform? obj10 = WitherholdFindChildByExactName(transform, "Firefly Particles");
					obj9 = ((obj10 != null) ? ((Component)obj10).GetComponent<ParticleSystem>() : null) ?? WitherholdCreateFallbackParticleSystem(transform, "Firefly Particles");
				}
			}
			ParticleSystem value12 = (ParticleSystem)obj9;
			WitherholdSetChargingStationField(chargingStation, "fireflyParticles", value12);
			object obj11 = WitherholdMapComponent<ParticleSystem>(transform, templateRoot, ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<ParticleSystem>(val, "bitsParticles") : null);
			if (obj11 == null)
			{
				obj11 = WitherholdGetChargingStationField<ParticleSystem>(chargingStation, "bitsParticles");
				if (obj11 == null)
				{
					Transform? obj12 = WitherholdFindChildByExactName(transform, "Bits Particles");
					obj11 = ((obj12 != null) ? ((Component)obj12).GetComponent<ParticleSystem>() : null) ?? WitherholdCreateFallbackParticleSystem(transform, "Bits Particles");
				}
			}
			ParticleSystem value13 = (ParticleSystem)obj11;
			WitherholdSetChargingStationField(chargingStation, "bitsParticles", value13);
			AnimationCurve val3 = WitherholdGetChargingStationField<AnimationCurve>(chargingStation, "chargeCurve");
			if (val3 == null || val3.length == 0)
			{
				AnimationCurve val4 = (((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<AnimationCurve>(val, "chargeCurve") : null);
				val3 = (AnimationCurve)((val4 == null || val4.length <= 0) ? ((object)AnimationCurve.EaseInOut(0f, 0f, 1f, 1f)) : ((object)new AnimationCurve(val4.keys)));
			}
			WitherholdSetChargingStationField(chargingStation, "chargeCurve", val3);
			Sound value14 = WitherholdEnsureChargingStationSound(WitherholdGetChargingStationField<Sound>(chargingStation, "soundStart"), ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<Sound>(val, "soundStart") : null, transform, templateRoot, "Sound Start", requireSource: false);
			WitherholdSetChargingStationField(chargingStation, "soundStart", value14);
			Sound value15 = WitherholdEnsureChargingStationSound(WitherholdGetChargingStationField<Sound>(chargingStation, "soundStop"), ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<Sound>(val, "soundStop") : null, transform, templateRoot, "Sound Stop", requireSource: false);
			WitherholdSetChargingStationField(chargingStation, "soundStop", value15);
			Sound value16 = WitherholdEnsureChargingStationSound(WitherholdGetChargingStationField<Sound>(chargingStation, "soundLoop"), ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<Sound>(val, "soundLoop") : null, transform, templateRoot, "Sound Loop", requireSource: true);
			WitherholdSetChargingStationField(chargingStation, "soundLoop", value16);
			Sound value17 = WitherholdEnsureChargingStationSound(WitherholdGetChargingStationField<Sound>(chargingStation, "soundPowerCrystalBreak"), ((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<Sound>(val, "soundPowerCrystalBreak") : null, transform, templateRoot, "Sound Crystal Break", requireSource: false);
			WitherholdSetChargingStationField(chargingStation, "soundPowerCrystalBreak", value17);
			Item value18 = WitherholdGetChargingStationField<Item>(chargingStation, "item") ?? (((Object)(object)val != (Object)null) ? WitherholdGetChargingStationField<Item>(val, "item") : null) ?? WitherholdFindPowerCrystalItem();
			WitherholdSetChargingStationField(chargingStation, "item", value18);
		}

		private static ChargingStation? WitherholdFindFallbackChargingStationTemplate()
		{
			if (RunManager.instance?.levels != null)
			{
				foreach (Level level in RunManager.instance.levels)
				{
					if (!((Object)(object)level == (Object)null) && !WitherholdIsWitherholdLevel(level))
					{
						GameObject val = WitherholdGetFirstValidPrefab(level.StartRooms);
						ChargingStation val2 = (((Object)(object)val != (Object)null) ? val.GetComponentInChildren<ChargingStation>(true) : null);
						if ((Object)(object)val2 != (Object)null)
						{
							return val2;
						}
					}
				}
			}
			return ((IEnumerable<ChargingStation>)Resources.FindObjectsOfTypeAll<ChargingStation>()).FirstOrDefault((Func<ChargingStation, bool>)delegate(ChargingStation candidate)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)candidate != (Object)null)
				{
					Scene scene = ((Component)candidate).gameObject.scene;
					return !((Scene)(ref scene)).IsValid();
				}
				return false;
			});
		}

		private static GameObject? WitherholdGetFirstValidPrefab(IEnumerable<PrefabRef>? prefabRefs)
		{
			if (prefabRefs == null)
			{
				return null;
			}
			foreach (PrefabRef prefabRef in prefabRefs)
			{
				if (prefabRef == null)
				{
					continue;
				}
				try
				{
					if ((Object)(object)prefabRef.Prefab != (Object)null)
					{
						return prefabRef.Prefab;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static Sound WitherholdEnsureChargingStationSound(Sound? currentSound, Sound? templateSound, Transform stationRoot, Transform? templateRoot, string audioName, bool requireSource)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (currentSound == null)
			{
				currentSound = new Sound();
			}
			WitherholdNormalizeSound(currentSound);
			if (templateSound != null)
			{
				currentSound.Sounds = templateSound.Sounds ?? Array.Empty<AudioClip>();
				currentSound.Type = templateSound.Type;
				currentSound.Volume = templateSound.Volume;
				WitherholdSetSoundVolumeDefault(currentSound, WitherholdGetSoundVolumeDefault(templateSound, currentSound.Volume));
				currentSound.VolumeRandom = templateSound.VolumeRandom;
				currentSound.Pitch = templateSound.Pitch;
				currentSound.PitchRandom = templateSound.PitchRandom;
				currentSound.SpatialBlend = templateSound.SpatialBlend;
				currentSound.Doppler = templateSound.Doppler;
				currentSound.ReverbMix = templateSound.ReverbMix;
				currentSound.FalloffMultiplier = templateSound.FalloffMultiplier;
				currentSound.OffscreenVolume = templateSound.OffscreenVolume;
				currentSound.OffscreenFalloff = templateSound.OffscreenFalloff;
				currentSound.Source = WitherholdMapComponent<AudioSource>(stationRoot, templateRoot, templateSound.Source) ?? currentSound.Source;
			}
			if (requireSource && (Object)(object)currentSound.Source == (Object)null)
			{
				currentSound.Source = WitherholdCreateFallbackAudioSource(stationRoot, audioName);
			}
			return currentSound;
		}

		private static float WitherholdGetSoundVolumeDefault(Sound? sound, float fallback)
		{
			if (sound == null)
			{
				return fallback;
			}
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(((object)sound).GetType(), "VolumeDefault");
				if (fieldInfo == null)
				{
					return fallback;
				}
				return (fieldInfo.GetValue(sound) is float num) ? num : fallback;
			}
			catch
			{
				return fallback;
			}
		}

		private static void WitherholdSetSoundVolumeDefault(Sound? sound, float value)
		{
			if (sound == null)
			{
				return;
			}
			try
			{
				AccessTools.Field(((object)sound).GetType(), "VolumeDefault")?.SetValue(sound, value);
			}
			catch
			{
			}
		}

		private static T? WitherholdGetChargingStationField<T>(ChargingStation? chargingStation, string fieldName)
		{
			return WitherholdGetChargingStationField(chargingStation, fieldName, default(T));
		}

		private static T WitherholdGetChargingStationField<T>(ChargingStation? chargingStation, string fieldName, T fallback)
		{
			if ((Object)(object)chargingStation == (Object)null)
			{
				return fallback;
			}
			try
			{
				return (T)((Traverse.Create((object)chargingStation).Field(fieldName).GetValue() is T val) ? ((object)val) : ((object)fallback));
			}
			catch
			{
				return fallback;
			}
		}

		private static void WitherholdSetChargingStationField(ChargingStation? chargingStation, string fieldName, object? value)
		{
			if ((Object)(object)chargingStation == (Object)null)
			{
				return;
			}
			try
			{
				Traverse.Create((object)chargingStation).Field(fieldName).SetValue(value);
			}
			catch
			{
			}
		}

		private static Transform? WitherholdFindChildByExactName(Transform root, string name)
		{
			string name2 = name;
			return ((IEnumerable<Transform>)((Component)root).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform child) => (Object)(object)child != (Object)null && string.Equals(((Object)child).name, name2, StringComparison.OrdinalIgnoreCase)));
		}

		private static Transform? WitherholdFindChildContaining(Transform root, string value)
		{
			string value2 = value;
			return ((IEnumerable<Transform>)((Component)root).GetComponentsInChildren<Transform>(true)).FirstOrDefault((Func<Transform, bool>)((Transform child) => (Object)(object)child != (Object)null && ((Object)child).name.IndexOf(value2, StringComparison.OrdinalIgnoreCase) >= 0));
		}

		private static string? WitherholdGetRelativePath(Transform root, Transform? target)
		{
			if ((Object)(object)root == (Object)null || (Object)(object)target == (Object)null)
			{
				return null;
			}
			if ((Object)(object)target == (Object)(object)root)
			{
				return string.Empty;
			}
			Stack<string> stack = new Stack<string>();
			Transform val = target;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
			{
				stack.Push(((Object)val).name);
				val = val.parent;
			}
			if ((Object)(object)val != (Object)(object)root)
			{
				return null;
			}
			return string.Join("/", stack);
		}

		private static Transform? WitherholdMapTransform(Transform targetRoot, Transform? templateRoot, Transform? templateTransform)
		{
			if ((Object)(object)targetRoot == (Object)null || (Object)(object)templateRoot == (Object)null || (Object)(object)templateTransform == (Object)null)
			{
				return null;
			}
			string text = WitherholdGetRelativePath(templateRoot, templateTransform);
			if (text == null)
			{
				return null;
			}
			if (text.Length != 0)
			{
				return targetRoot.Find(text);
			}
			return targetRoot;
		}

		private static TComponent? WitherholdMapComponent<TComponent>(Transform targetRoot, Transform? templateRoot, TComponent? templateComponent) where TComponent : Component
		{
			Transform val = WitherholdMapTransform(targetRoot, templateRoot, ((Object)(object)templateComponent != (Object)null) ? ((Component)templateComponent).transform : null);
			if (!((Object)(object)val != (Object)null))
			{
				return default(TComponent);
			}
			return ((Component)val).GetComponent<TComponent>();
		}

		private static GameObject? WitherholdMapGameObject(Transform targetRoot, Transform? templateRoot, GameObject? templateObject)
		{
			Transform val = WitherholdMapTransform(targetRoot, templateRoot, ((Object)(object)templateObject != (Object)null) ? templateObject.transform : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).gameObject;
		}

		private static GameObject? WitherholdFindBestRendererGameObject(Transform root)
		{
			Transform root2 = root;
			return (from renderer in (from renderer in ((Component)root2).GetComponentsInChildren<Renderer>(true)
					where (Object)(object)renderer != (Object)null && (Object)(object)((Component)renderer).gameObject != (Object)(object)((Component)root2).gameObject
					select renderer).OrderByDescending(delegate(Renderer renderer)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0006: Unknown result type (might be due to invalid IL or missing references)
					//IL_0009: Unknown result type (might be due to invalid IL or missing references)
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					Bounds bounds = renderer.bounds;
					Vector3 size = ((Bounds)(ref bounds)).size;
					return ((Vector3)(ref size)).sqrMagnitude;
				})
				select ((Component)renderer).gameObject).FirstOrDefault();
		}

		private static GameObject WitherholdCreateFallbackMeshObject(Transform stationRoot)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)obj).name = "Charging Station Mesh";
			obj.transform.SetParent(stationRoot, false);
			obj.transform.localPosition = new Vector3(0f, 0.45f, 0f);
			obj.transform.localScale = new Vector3(0.75f, 0.9f, 0.6f);
			Collider component = obj.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			WitherholdApplyHideFlags((Object)(object)obj);
			return obj;
		}

		private static Transform WitherholdCreateFallbackAnchor(Transform stationRoot, string name, Vector3 localPosition, Vector3 localScale)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_002f: 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)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.transform.SetParent(stationRoot, false);
			val.transform.localPosition = localPosition;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = localScale;
			WitherholdApplyHideFlags((Object)val);
			return val.transform;
		}

		private static Transform WitherholdCreateFallbackCrystalCylinder(Transform stationRoot, int crystalCount)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Crystal Cylinder");
			val.transform.SetParent(stationRoot, false);
			val.transform.localPosition = new Vector3(0f, 0.6f, 0f);
			val.transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
			WitherholdApplyHideFlags((Object)(object)val);
			int num = Mathf.Max(1, crystalCount);
			for (int i = 0; i < num; i++)
			{
				GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3);
				((Object)obj).name = $"Crystal {i + 1}";
				obj.transform.SetParent(val.transform, false);
				float num2 = MathF.PI * 2f * (float)i / (float)num;
				obj.transform.localPosition = new Vector3(Mathf.Cos(num2) * 0.18f, Mathf.Sin(num2) * 0.18f, 0f);
				obj.transform.localScale = new Vector3(0.07f, 0.07f, 0.18f);
				Collider component = obj.GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component);
				}
			}
			return val.transform;
		}

		private static Light WitherholdCreateFallbackLight(Transform stationRoot, string name, Vector3 localPosition, float intensity)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(stationRoot, false);
			val.transform.localPosition = localPosition;
			Light obj = val.AddComponent<Light>();
			obj.type = (LightType)2;
			obj.range = 2f;
			obj.intensity = intensity;
			obj.color = new Color(1f, 0.9f, 0.35f);
			WitherholdApplyHideFlags((Object)(object)val);
			return obj;
		}

		private static Light WitherholdCreateFallbackSubtleLight(Transform stationRoot)
		{
			//IL_0015: 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)
			Light obj = WitherholdCreateFallbackLight(stationRoot, "Subtle Light", new Vector3(0f, 0.55f, 0.05f), 0.5f);
			obj.range = 2.5f;
			obj.color = new Color(0.7f, 0.7f, 0.3f);
			return obj;
		}

		private static ParticleSystem WitherholdCreateFallbackParticleSystem(Transform stationRoot, string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001a: 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)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(stationRoot, false);
			val.transform.localPosition = Vector3.zero;
			ParticleSystem obj = val.AddComponent<ParticleSystem>();
			MainModule main = obj.main;
			((MainModule)(ref main)).playOnAwake = false;
			((MainModule)(ref main)).loop = false;
			((MainModule)(ref main)).duration = 0.25f;
			((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(0.15f);
			((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.05f);
			((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.02f);
			EmissionModule emission = obj.emission;
			((EmissionModule)(ref emission)).enabled = false;
			WitherholdApplyHideFlags((Object)(object)val);
			return obj;
		}

		private static AudioSource WitherholdCreateFallbackAudioSource(Transform stationRoot, string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(stationRoot, false);
			val.transform.localPosition = Vector3.zero;
			AudioSource obj = val.AddComponent<AudioSource>();
			obj.playOnAwake = false;
			obj.spatialBlend = 1f;
			obj.outputAudioMixerGroup = WitherholdGetFallbackAudioMixerGroup();
			WitherholdApplyHideFlags((Object)(object)val);
			return obj;
		}

		private static Item? WitherholdFindPowerCrystalItem()
		{
			return ((IEnumerable<Item>)Resources.FindObjectsOfTypeAll<Item>()).FirstOrDefault((Func<Item, bool>)((Item item) => (Object)(object)item != (Object)null && (string.Equals(item.itemName, "Power Crystal", StringComparison.OrdinalIgnoreCase) || string.Equals(((Object)item).name, "Item Power Crystal", StringComparison.OrdinalIgnoreCase) || ((Object)item).name.IndexOf("Power Crystal", StringComparison.OrdinalIgnoreCase) >= 0)));
		}

		internal static void WitherholdEnsurePhysGrabHingeCompatibility(PhysGrabHinge? hinge)
		{
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Expected O, but got Unknown
			PhysGrabHinge hinge2 = hinge;
			if ((Object)(object)hinge2 == (Object)null)
			{
				return;
			}
			PhysGrabHinge val = hinge2;
			if (val.moveLoop == null)
			{
				val.moveLoop = WitherholdCreateFallbackSound();
			}
			if ((Object)(object)hinge2.hingeAudio == (Object)null)
			{
				hinge2.hingeAudio = WitherholdCreateFallbackHingeAudio();
			}
			else
			{
				WitherholdNormalizeSound(hinge2.hingeAudio.moveLoop);
				WitherholdNormalizeSound(hinge2.hingeAudio.moveLoopEnd);
				WitherholdNormalizeSound(hinge2.hingeAudio.Close);
				WitherholdNormalizeSound(hinge2.hingeAudio.CloseHeavy);
				WitherholdNormalizeSound(hinge2.hingeAudio.Open);
				WitherholdNormalizeSound(hinge2.hingeAudio.OpenHeavy);
				WitherholdNormalizeSound(hinge2.hingeAudio.HingeBreak);
			}
			val = hinge2;
			if (val.audioSource == null)
			{
				val.audioSource = ((Component)hinge2).GetComponent<AudioSource>() ?? ((Component)hinge2).gameObject.AddComponent<AudioSource>();
			}
			hinge2.audioSource.playOnAwake = false;
			if ((Object)(object)hinge2.audioSource.outputAudioMixerGroup == (Object)null)
			{
				hinge2.audioSource.outputAudioMixerGroup = WitherholdGetFallbackAudioMixerGroup();
			}
			if ((Object)(object)((Component)hinge2).GetComponent<HingeJoint>() == (Object)null)
			{
				((Component)hinge2).gameObject.AddComponent<HingeJoint>();
			}
			if ((Object)(object)((Component)hinge2).GetComponent<PhysGrabObjectImpactDetector>() == (Object)null)
			{
				((Component)hinge2).gameObject.AddComponent<PhysGrabObjectImpactDetector>();
			}
			if ((Object)(object)hinge2.hingePoint == (Object)null)
			{
				Rigidbody val2 = ((IEnumerable<Rigidbody>)((Component)hinge2).GetComponentsInChildren<Rigidbody>(true)).FirstOrDefault((Func<Rigidbody, bool>)((Rigidbody rigidbody) => (Object)(object)rigidbody != (Object)null && (Object)(object)((Component)rigidbody).transform != (Object)(object)((Component)hinge2).transform));
				if ((Object)(object)val2 != (Object)null)
				{
					hinge2.hingePoint = ((Component)val2).transform;
				}
				else if (((Component)hinge2).transform.childCount > 0)
				{
					hinge2.hingePoint = ((Component)hinge2).transform.GetChild(0);
				}
				else
				{
					GameObject val3 = new GameObject("Witherhold Keep Patch Hinge Point");
					val3.transform.SetParent(((Component)hinge2).transform, false);
					WitherholdApplyHideFlags((Object)(object)val3);
					hinge2.hingePoint = val3.transform;
				}
			}
			val = hinge2;
			if (val.wallTagHinges == null)
			{
				val.wallTagHinges = Array.Empty<PhysGrabHinge>();
			}
			val = hinge2;
			if (val.wallTagObjects == null)
			{
				val.wallTagObjects = Array.Empty<GameObject>();
			}
			val = hinge2;
			if (val.lowPassTriggers == null)
			{
				val.lowPassTriggers = Array.Empty<LowPassTrigger>();
			}
		}

		private static HingeAudio WitherholdCreateFallbackHingeAudio()
		{
			HingeAudio obj = ScriptableObject.CreateInstance<HingeAudio>();
			obj.moveLoopEnabled = false;
			obj.moveLoop = WitherholdCreateFallbackSound();
			obj.moveLoopEnd = WitherholdCreateFallbackSound();
			obj.Close = WitherholdCreateFallbackSound();
			obj.CloseHeavy = WitherholdCreateFallbackSound();
			obj.Open = WitherholdCreateFallbackSound();
			obj.OpenHeavy = WitherholdCreateFallbackSound();
			obj.HingeBreak = WitherholdCreateFallbackSound();
			WitherholdApplyHideFlags((Object)(object)obj);
			return obj;
		}

		private static Sound WitherholdCreateFallbackSound()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_000c: Expected O, but got Unknown
			Sound val = new Sound();
			WitherholdNormalizeSound(val);
			return val;
		}

		private static void WitherholdNormalizeSound(Sound? sound)
		{
			if (sound != null)
			{
				Sound val = sound;
				if (val.Sounds == null)
				{
					val.Sounds = Array.Empty<AudioClip>();
				}
				val = sound;
				if (val.LowPassIgnoreColliders == null)
				{
					val.LowPassIgnoreColliders = new List<Collider>();
				}
			}
		}

		private static PhysAttribute WitherholdCreateFallbackPhysAttribute(float mass)
		{
			PhysAttribute obj = ScriptableObject.CreateInstance<PhysAttribute>();
			obj.mass = Mathf.Max(0.01f, mass);
			WitherholdApplyHideFlags((Object)(object)obj);
			return obj;
		}

		private static AudioMixerGroup? WitherholdGetFallbackAudioMixerGroup()
		{
			if ((Object)(object)AudioManager.instance == (Object)null)
			{
				return null;
			}
			return AudioManager.instance.SoundMasterGroup ?? AudioManager.instance.PersistentSoundGroup ?? AudioManager.instance.MusicMasterGroup ?? AudioManager.instance.MicrophoneSoundGroup ?? AudioManager.instance.MicrophoneSpectateGroup ?? AudioManager.instance.TTSSoundGroup ?? AudioManager.instance.TTSSpectateGroup;
		}

		private static int WitherholdCountModules(Level level)
		{
			return (level.ModulesNormal1?.Count ?? 0) + (level.ModulesPassage1?.Count ?? 0) + (level.ModulesDeadEnd1?.Count ?? 0) + (level.ModulesExtraction1?.Count ?? 0) + (level.ModulesNormal2?.Count ?? 0) + (level.ModulesPassage2?.Count ?? 0) + (level.ModulesDeadEnd2?.Count ?? 0) + (level.ModulesExtraction2?.Count ?? 0) + (level.ModulesNormal3?.Count ?? 0) + (level.ModulesPassage3?.Count ?? 0) + (level.ModulesDeadEnd3?.Count ?? 0) + (level.ModulesExtraction3?.Count ?? 0);
		}

		private static int WitherholdCountValidModules(Level level)
		{
			return WitherholdCountValidPrefabRefs(level.ModulesNormal1) + WitherholdCountValidPrefabRefs(level.ModulesPassage1) + WitherholdCountValidPrefabRefs(level.ModulesDeadEnd1) + WitherholdCountValidPrefabRefs(level.ModulesExtraction1) + WitherholdCountValidPrefabRefs(level.ModulesNormal2) + WitherholdCountValidPrefabRefs(level.ModulesPassage2) + WitherholdCountValidPrefabRefs(level.ModulesDeadEnd2) + WitherholdCountValidPrefabRefs(level.ModulesExtraction2) + WitherholdCountValidPrefabRefs(level.ModulesNormal3) + WitherholdCountValidPrefabRefs(level.ModulesPassage3) + WitherholdCountValidPrefabRefs(level.ModulesDeadEnd3) + WitherholdCountValidPrefabRefs(level.ModulesExtraction3);
		}

		private static int WitherholdCountValidPrefabRefs(IEnumerable<PrefabRef>? prefabRefs)
		{
			if (prefabRefs == null)
			{
				return 0;
			}
			int num = 0;
			foreach (PrefabRef prefabRef in prefabRefs)
			{
				if (prefabRef != null && (!string.IsNullOrWhiteSpace(prefabRef.ResourcePath) || (Object)(object)prefabRef.Prefab != (Object)null))
				{
					num++;
				}
			}
			return num;
		}

		internal static bool WitherholdIsCurrentLevel()
		{
			if (!WitherholdIsWitherholdLevel(((Object)(object)LevelGenerator.Instance != (Object)null) ? LevelGenerator.Instance.Level : null))
			{
				return WitherholdIsWitherholdLevel(((Object)(object)RunManager.instance != (Object)null) ? RunManager.instance.levelCurrent : null);
			}
			return true;
		}

		internal static bool WitherholdShouldSuppressMissingScriptWarning(LogType logType, string? format, object[]? args)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			if ((int)logType != 2 || !WitherholdIsCurrentLevel())
			{
				return false;
			}
			if (WitherholdIsMissingScriptWarning(format))
			{
				return true;
			}
			if (args == null || args.Length == 0 || string.IsNullOrWhiteSpace(format))
			{
				return false;
			}
			try
			{
				return WitherholdIsMissingScriptWarning(string.Format(format, args));
			}
			catch
			{
				return false;
			}
		}

		internal static bool WitherholdShouldSuppressMissingScriptWarning(LogEventArgs? eventArgs)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (eventArgs == null || (int)eventArgs.Level != 4 || !WitherholdIsCurrentLevel())
			{
				return false;
			}
			if (!WitherholdIsUnityLogSource(eventArgs.Source))
			{
				return false;
			}
			if (eventArgs.Data is string message)
			{
				return WitherholdIsMissingScriptWarning(message);
			}
			return WitherholdIsMissingScriptWarning(eventArgs.Data?.ToString());
		}

		private static bool WitherholdIsUnityLogSource(ILogSource? source)
		{
			if (source != null)
			{
				return string.Equals(source.SourceName, "Unity Log", StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		private static bool WitherholdIsMissingScriptWarning(string? message)
		{
			if (string.IsNullOrWhiteSpace(message))
			{
				return false;
			}
			if (message.IndexOf("The referenced script", StringComparison.Ordinal) >= 0)
			{
				return message.IndexOf("missing", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static bool WitherholdSuppressMissingScriptWarningPrefix(LogType logType, string format, object[] args)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return !WitherholdShouldSuppressMissingScriptWarning(logType, format, args);
		}

		internal static bool WitherholdIsWitherholdLevel(Level? level)
		{
			if ((Object)(object)level == (Object)null)
			{
				return false;
			}
			if (!string.Equals(((Object)level).name, "Level - Witherhold", StringComparison.OrdinalIgnoreCase) && !string.Equals(level.ResourcePath, "Witherhold", StringComparison.OrdinalIgnoreCase) && (string.IsNullOrWhiteSpace(((Object)level).name) || ((Object)level).name.IndexOf("witherhold", StringComparison.OrdinalIgnoreCase) < 0 || ((Object)level).name.IndexOf("keep", StringComparison.OrdinalIgnoreCase) < 0))
			{
				if (!string.IsNullOrWhiteSpace(level.ResourcePath) && level.ResourcePath.IndexOf("witherhold", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return level.ResourcePath.IndexOf("keep", StringComparison.OrdinalIgnoreCase) >= 0;
				}
				return false;
			}
			return true;
		}

		internal static void WitherholdEnsureLevelFallbackData(Level? level)
		{
			if (WitherholdIsWitherholdLevel(level))
			{
				level.ResourcePath = (string.IsNullOrWhiteSpace(level.ResourcePath) ? "Witherhold" : level.ResourcePath);
				level.NarrativeName = (string.IsNullOrWhiteSpace(level.NarrativeName) ? "Witherhold Keep" : level.NarrativeName);
				level.ModuleAmount = Mathf.Max(level.ModuleAmount, 8);
				level.PassageMaxAmount = Mathf.Max(level.PassageMaxAmount, 4);
				Level val = level;
				if (val.ValuablePresets == null)
				{
					val.ValuablePresets = new List<LevelValuables>();
				}
				val = level;
				if (val.AmbiencePresets == null)
				{
					val.AmbiencePresets = new List<LevelAmbience>();
				}
				if (level.ValuablePresets.Count == 0 && (Object)(object)ValuablePresets.GenericValuablePreset != (Object)null)
				{
					level.ValuablePresets.Add(ValuablePresets.GenericValuablePreset);
				}
				if (level.AmbiencePresets.Count == 0 && WitherholdTryGetFallbackAmbience(out LevelAmbience ambience))
				{
					level.AmbiencePresets.Add(ambience);
				}
			}
		}

		private static bool WitherholdTryGetFallbackAmbience(out LevelAmbience ambience)
		{
			ambience = null;
			if ((Object)(object)AudioManager.instance != (Object)null && AudioManager.instance.levelAmbiences != null)
			{
				foreach (LevelAmbience levelAmbience in AudioManager.instance.levelAmbiences)
				{
					if (!((Object)(object)levelAmbience == (Object)null))
					{
						ambience = levelAmbience;
						return true;
					}
				}
			}
			if ((Object)(object)RunManager.instance != (Object)null && RunManager.instance.levels != null)
			{
				foreach (Level level in RunManager.instance.levels)
				{
					if (level?.AmbiencePresets == null)
					{
						continue;
					}
					foreach (LevelAmbience ambiencePreset in level.AmbiencePresets)
					{
						if (!((Object)(object)ambiencePreset == (Object)null))
						{
							ambience = ambiencePreset;
							return true;
						}
					}
				}
			}
			return false;
		}

		internal static void WitherholdEnsureExtractionPointCompatibility(ExtractionPoint extractionPoint)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			if ((Object)(object)extractionPoint == (Object)null || !WitherholdIsCurrentLevel())
			{
				return;
			}
			if ((Object)(object)extractionPoint.extractionArea == (Object)null)
			{
				GameObject val = GameObject.CreatePrimitive((PrimitiveType)2);
				((Object)val).name = "Witherhold Keep Patch Extraction Area";
				val.transform.SetParent(((Component)extractionPoint).transform, false);
				val.transform.localPosition = Vector3.zero;
				val.transform.localRotation = Quaternion.identity;
				val.transform.localScale = Vector3.one * 0.1f;
				MeshRenderer component = val.GetComponent<MeshRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					((Renderer)component).enabled = false;
				}
				Collider component2 = val.GetComponent<Collider>();
				if ((Object)(object)component2 != (Object)null)
				{
					Object.Destroy((Object)(object)component2);
				}
				val.SetActive(false);
				WitherholdApplyHideFlags((Object)(object)val);
				extractionPoint.extractionArea = val;
			}
			if ((Object)(object)extractionPoint.grossUp == (Object)null)
			{
				GameObject val2 = new GameObject("Witherhold Keep Patch GrossUp");
				val2.transform.SetParent(((Component)extractionPoint).transform, false);
				val2.SetActive(false);
				WitherholdApplyHideFlags((Object)(object)val2);
				extractionPoint.grossUp = val2;
			}
		}

		internal void WitherholdRepairLevelPoints(LevelGenerator levelGenerator)
		{
			if ((Object)(object)levelGenerator == (Object)null || !WitherholdIsWitherholdLevel(levelGenerator.Level) || levelGenerator.LevelPathPoints == null)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			foreach (LevelPoint levelPathPoint in levelGenerator.LevelPathPoints)
			{
				if (WitherholdRepairLevelPoint(levelPathPoint))
				{
					num++;
				}
				if (WitherholdRepairLevelPointRoom(levelPathPoint))
				{
					num2++;
				}
			}
			if (num > 0 || num2 > 0)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Empress Witherhold Keep Compat Patch repaired {num} Witherhold Keep level points onto the navmesh and restored {num2} room links.");
			}
		}

		private static bool WitherholdRepairLevelPoint(LevelPoint? levelPoint)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)levelPoint == (Object)null)
			{
				return false;
			}
			Vector3 position = ((Component)levelPoint).transform.position;
			NavMeshHit val = default(NavMeshHit);
			if (NavMesh.SamplePosition(position, ref val, 0.5f, -1))
			{
				return false;
			}
			NavMeshHit val2 = default(NavMeshHit);
			if (!NavMesh.SamplePosition(position, ref val2, 2f, -1))
			{
				return false;
			}
			((Component)levelPoint).transform.position = ((NavMeshHit)(ref val2)).position;
			WitherholdRepairLevelPointRoom(levelPoint);
			return true;
		}

		private static bool WitherholdRepairLevelPointRoom(LevelPoint? levelPoint)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)levelPoint == (Object)null || (Object)(object)levelPoint.Room != (Object)null)
			{
				return false;
			}
			RoomVolume room = default(RoomVolume);
			Vector3 val = default(Vector3);
			if (!SemiFunc.GetRoomVolumeAtPosition(((Component)levelPoint).transform.position, ref room, ref val))
			{
				return false;
			}
			levelPoint.Room = room;
			return true;
		}

		internal IEnumerator WitherholdSilentLevelPointCheck(LevelPoint levelPoint)
		{
			if (!((Object)(object)levelPoint == (Object)null))
			{
				while ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
				{
					yield return (object)new WaitForSeconds(0.1f);
				}
				yield return (object)new WaitForSeconds(0.5f);
				if (WitherholdIsCurrentLevel())
				{
					WitherholdRepairLevelPoint(levelPoint);
					WitherholdRepairLevelPointRoom(levelPoint);
					WitherholdRepairLevelPointConnections(levelPoint, LevelGenerator.Instance?.LevelPathPoints);
				}
			}
		}

		private static void WitherholdRepairLevelPointConnections(LevelPoint? levelPoint, IList<LevelPoint>? allLevelPoints)
		{
			if ((Object)(object)levelPoint == (Object)null)
			{
				return;
			}
			if (levelPoint.ConnectedPoints == null)
			{
				levelPoint.ConnectedPoints = new List<LevelPoint>();
			}
			levelPoint.ConnectedPoints.RemoveAll((LevelPoint connectedPoint) => (Object)(object)connectedPoint == (Object)null);
			LevelPoint[] array = levelPoint.ConnectedPoints.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				WitherholdAddLevelPointConnection(array[i], levelPoint);
			}
			if (!levelPoint.ModuleConnect || allLevelPoints == null || levelPoint.ConnectedPoints.Count > 0)
			{
				return;
			}
			LevelPoint val = null;
			float currentBestDistance = float.MaxValue;
			foreach (LevelPoint allLevelPoint in allLevelPoints)
			{
				if (WitherholdCanConnectLevelPoints(levelPoint, allLevelPoint, currentBestDistance, out var distance))
				{
					val = allLevelPoint;
					currentBestDistance = distance;
				}
			}
			WitherholdAddLevelPointConnection(levelPoint, val);
			WitherholdAddLevelPointConnection(val, levelPoint);
		}

		private static bool WitherholdCanConnectLevelPoints(LevelPoint source, LevelPoint? candidate, float currentBestDistance, out float distance)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			distance = 0f;
			if ((Object)(object)source == (Object)null || (Object)(object)candidate == (Object)null || (Object)(object)source == (Object)(object)candidate || !candidate.ModuleConnect)
			{
				return false;
			}
			Vector3 val = ((Component)source).transform.position - ((Component)candidate).transform.position;
			if (((Vector3)(ref val)).sqrMagnitude <= Mathf.Epsilon)
			{
				return false;
			}
			distance = ((Vector3)(ref val)).magnitude;
			if (distance >= 15f || distance >= currentBestDistance)
			{
				return false;
			}
			if (Vector3.Dot(((Component)candidate).transform.forward, ((Component)source).transform.forward) > -0.8f)
			{
				return false;
			}
			return Vector3.Dot(((Component)candidate).transform.forward, ((Vector3)(ref val)).normalized) > 0.8f;
		}

		private static void WitherholdAddLevelPointConnection(LevelPoint? source, LevelPoint? target)
		{
			if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null))
			{
				if (source.ConnectedPoints == null)
				{
					source.ConnectedPoints = new List<LevelPoint>();
				}
				if (!source.ConnectedPoints.Contains(target))
				{
					source.ConnectedPoints.Add(target);
				}
			}
		}

		internal GameObject WitherholdCreateFallbackDoorMapObject(Map map, DirtFinderMapDoor door)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			MapLayer layerParent = map.GetLayerParent(((Component)door).transform.position.y);
			GameObject val = WitherholdInstantiateFallbackDoorMapObject(map, ((Component)layerParent).transform);
			((Object)val).name = ((Object)((Component)door).gameObject).name;
			door.Target = val.transform;
			DirtFinderMapDoorTarget val2 = val.GetComponent<DirtFinderMapDoorTarget>() ?? val.AddComponent<DirtFinderMapDoorTarget>();
			val2.Target = ((Component)door).transform;
			val2.Layer = layerParent;
			DirtFinderMapDoorTarget val3 = val2;
			if (val3.HingeTransform == null)
			{
				val3.HingeTransform = val.transform;
			}
			map.DoorUpdate(val2.HingeTransform, ((Component)door).transform, layerParent);
			if (!_witherholdLoggedDoorMapFallback)
			{
				_witherholdLoggedDoorMapFallback = true;
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Empress Witherhold Keep Compat Patch injected fallback minimap door markers for missing Witherhold Keep door prefabs.");
			}
			return val;
		}

		private static GameObject WitherholdInstantiateFallbackDoorMapObject(Map map, Transform parent)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val;
			if ((Object)(object)map.Door1x1Object != (Object)null)
			{
				val = Object.Instantiate<GameObject>(map.Door1x1Object, parent);
				Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren[i]);
				}
			}
			else
			{
				val = GameObject.CreatePrimitive((PrimitiveType)3);
				val.transform.SetParent(parent, false);
				val.transform.localScale = new Vector3(0.12f, 0.12f, 0.3f);
				Collider component = val.GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
			}
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			DirtFinderMapDoorTarget val2 = val.GetComponent<DirtFinderMapDoorTarget>() ?? val.AddComponent<DirtFinderMapDoorTarget>();
			if (val2.HingeTransform == null)
			{
				val2.HingeTransform = val.transform;
			}
			WitherholdApplyHideFlags((Object)(object)val);
			return val;
		}

		private static void WitherholdApplyHideFlags(Object obj)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (obj == (Object)null)
			{
				return;
			}
			obj.hideFlags = (HideFlags)(obj.hideFlags | 0x23);
			GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null);
			if (val == null)
			{
				return;
			}
			Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true);
			foreach (Transform obj2 in componentsInChildren)
			{
				((Object)obj2).hideFlags = (HideFlags)(((Object)obj2).hideFlags | 0x23);
				GameObject gameObject = ((Component)obj2).gameObject;
				((Object)gameObject).hideFlags = (HideFlags)(((Object)gameObject).hideFlags | 0x23);
				Component[] components = ((Component)obj2).GetComponents<Component>();
				foreach (Component val2 in components)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						((Object)val2).hideFlags = (HideFlags)(((Object)val2).hideFlags | 0x23);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "StartRoomGeneration")]
	internal static class WitherholdKeepCompatPatchStartRoomGenerationPatch
	{
		[HarmonyPrefix]
		private static void WitherholdPrefix()
		{
			WitherholdKeepCompatPatchPlugin.Instance?.WitherholdTryRepairCurrentLevel();
		}
	}
	[HarmonyPatch(typeof(PhysGrabHinge), "Awake")]
	internal static class WitherholdKeepCompatPatchPhysGrabHingeAwakePatch
	{
		[HarmonyPrefix]
		private static void WitherholdPrefix(PhysGrabHinge __instance)
		{
			if (WitherholdKeepCompatPatchPlugin.WitherholdIsCurrentLevel())
			{
				WitherholdKeepCompatPatchPlugin.WitherholdEnsurePhysGrabHingeCompatibility(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint), "Start")]
	internal static class WitherholdKeepCompatPatchExtractionPointStartPatch
	{
		[HarmonyPostfix]
		private static void WitherholdPostfix(ExtractionPoint __instance)
		{
			WitherholdKeepCompatPatchPlugin.WitherholdEnsureExtractionPointCompatibility(__instance);
		}
	}
	[HarmonyPatch(typeof(ChargingStation), "Start")]
	internal static class WitherholdKeepCompatPatchChargingStationStartPatch
	{
		[HarmonyPrefix]
		private static void WitherholdPrefix(ChargingStation __instance)
		{
			if (WitherholdKeepCompatPatchPlugin.WitherholdIsCurrentLevel())
			{
				WitherholdKeepCompatPatchPlugin.WitherholdEnsureChargingStationCompatibility(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Levels), "RegisterLevelWithGame")]
	internal static class WitherholdKeepCompatPatchRegisterLevelPatch
	{
		[HarmonyPrefix]
		private static void WitherholdPrefix(Level level)
		{
			WitherholdKeepCompatPatchPlugin.WitherholdEnsureLevelFallbackData(level);
		}
	}
	[HarmonyPatch(typeof(Map), "AddDoor")]
	internal static class WitherholdKeepCompatPatchMapAddDoorPatch
	{
		[HarmonyPrefix]
		private static bool WitherholdPrefix(Map __instance, DirtFinderMapDoor door, GameObject doorPrefab, ref GameObject __result)
		{
			if (!WitherholdKeepCompatPatchPlugin.WitherholdIsCurrentLevel() || (Object)(object)door == (Object)null || (Object)(object)doorPrefab != (Object)null)
			{
				return true;
			}
			WitherholdKeepCompatPatchPlugin instance = WitherholdKeepCompatPatchPlugin.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return true;
			}
			__result = instance.WitherholdCreateFallbackDoorMapObject(__instance, door);
			return false;
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "NavMeshSetupRPC")]
	internal static class WitherholdKeepCompatPatchNavMeshSetupPatch
	{
		[HarmonyPostfix]
		private static void WitherholdPostfix(LevelGenerator __instance)
		{
			WitherholdKeepCompatPatchPlugin.Instance?.WitherholdRepairLevelPoints(__instance);
		}
	}
	[HarmonyPatch(typeof(LevelPoint), "NavMeshCheck")]
	internal static class WitherholdKeepCompatPatchLevelPointNavMeshCheckPatch
	{
		[HarmonyPrefix]
		private static bool WitherholdPrefix(LevelPoint __instance, ref IEnumerator __result)
		{
			if (!WitherholdKeepCompatPatchPlugin.WitherholdIsCurrentLevel())
			{
				return true;
			}
			WitherholdKeepCompatPatchPlugin instance = WitherholdKeepCompatPatchPlugin.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return true;
			}
			__result = instance.WitherholdSilentLevelPointCheck(__instance);
			return false;
		}
	}
	[HarmonyPatch(typeof(UnityLogListener), "LogEvent")]
	internal static class WitherholdKeepCompatPatchUnityLogListenerPatch
	{
		[HarmonyPrefix]
		private static bool WitherholdPrefix(LogEventArgs eventArgs)
		{
			return !WitherholdKeepCompatPatchPlugin.WitherholdShouldSuppressMissingScriptWarning(eventArgs);
		}
	}
	[HarmonyPatch(typeof(UnityLogSource), "UnityLogMessageHandler")]
	internal static class WitherholdKeepCompatPatchUnityLogSourcePatch
	{
		[HarmonyPrefix]
		private static bool WitherholdPrefix(LogEventArgs eventArgs)
		{
			return !WitherholdKeepCompatPatchPlugin.WitherholdShouldSuppressMissingScriptWarning(eventArgs);
		}
	}
	[HarmonyPatch(typeof(Logger), "InternalLogEvent")]
	internal static class WitherholdKeepCompatPatchInternalLogEventPatch
	{
		[HarmonyPrefix]
		private static bool WitherholdPrefix(LogEventArgs eventArgs)
		{
			return !WitherholdKeepCompatPatchPlugin.WitherholdShouldSuppressMissingScriptWarning(eventArgs);
		}
	}
}