Decompiled source of AllMapMerge v4.0.0

AllMapMerge.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("REPOJP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabuMod")]
[assembly: AssemblyTitle("zabuMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOJPAllMapMerge
{
	[BepInPlugin("REPOJP.AllMapMerge", "AllMapMerge", "4.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private class RoomEntry
		{
			public PrefabRef PrefabRef;

			public Level SourceLevel;

			public RoomEntry(PrefabRef prefabRef, Level sourceLevel)
			{
				PrefabRef = prefabRef;
				SourceLevel = sourceLevel;
			}
		}

		private class CategoryUsage
		{
			public readonly HashSet<string> UsedPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		}

		private class CategoryPool
		{
			public readonly List<RoomEntry> Entries = new List<RoomEntry>();

			private readonly HashSet<string> uniquePaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

			public int UniqueCount => uniquePaths.Count;

			public void Add(RoomEntry entry)
			{
				if (entry != null && IsValidPrefabRef(entry.PrefabRef))
				{
					Entries.Add(entry);
					uniquePaths.Add(entry.PrefabRef.ResourcePath);
				}
			}

			public bool ContainsResourcePath(string resourcePath)
			{
				if (string.IsNullOrEmpty(resourcePath))
				{
					return false;
				}
				return uniquePaths.Contains(resourcePath);
			}

			public RoomEntry ChoosePreferDifferentSource(HashSet<Level> avoidSourceLevels, CategoryUsage usage, RoomEntry currentEntry)
			{
				if (Entries.Count <= 0)
				{
					return null;
				}
				if (NoRepeatUntilPoolExhausted != null && NoRepeatUntilPoolExhausted.Value && usage != null && usage.UsedPaths.Count >= UniqueCount)
				{
					usage.UsedPaths.Clear();
				}
				List<RoomEntry> list = BuildCandidateList(avoidSourceLevels, usage, enforceAvoidSources: true);
				if (list.Count <= 0)
				{
					list = BuildCandidateList(avoidSourceLevels, usage, enforceAvoidSources: false);
				}
				if (list.Count <= 0)
				{
					list = BuildCandidateList(null, usage, enforceAvoidSources: true);
				}
				if (list.Count <= 0)
				{
					list = new List<RoomEntry>(Entries);
				}
				if (currentEntry != null)
				{
					int num = CalculateConflictScore(currentEntry, avoidSourceLevels);
					List<RoomEntry> list2 = new List<RoomEntry>();
					for (int i = 0; i < list.Count; i++)
					{
						RoomEntry roomEntry = list[i];
						if (roomEntry != null && CalculateConflictScore(roomEntry, avoidSourceLevels) < num)
						{
							list2.Add(roomEntry);
						}
					}
					if (list2.Count <= 0)
					{
						return currentEntry;
					}
					list = list2;
				}
				RoomEntry roomEntry2 = list[Random.Range(0, list.Count)];
				if (roomEntry2 != null && usage != null && NoRepeatUntilPoolExhausted != null && NoRepeatUntilPoolExhausted.Value && !string.IsNullOrEmpty(roomEntry2.PrefabRef.ResourcePath))
				{
					usage.UsedPaths.Add(roomEntry2.PrefabRef.ResourcePath);
				}
				return roomEntry2;
			}

			private List<RoomEntry> BuildCandidateList(HashSet<Level> avoidSourceLevels, CategoryUsage usage, bool enforceAvoidSources)
			{
				List<RoomEntry> list = new List<RoomEntry>();
				for (int i = 0; i < Entries.Count; i++)
				{
					RoomEntry roomEntry = Entries[i];
					if (roomEntry != null && IsValidPrefabRef(roomEntry.PrefabRef) && (!enforceAvoidSources || avoidSourceLevels == null || avoidSourceLevels.Count <= 0 || !((Object)(object)roomEntry.SourceLevel != (Object)null) || !avoidSourceLevels.Contains(roomEntry.SourceLevel)) && (NoRepeatUntilPoolExhausted == null || !NoRepeatUntilPoolExhausted.Value || usage == null || !usage.UsedPaths.Contains(roomEntry.PrefabRef.ResourcePath)))
					{
						list.Add(roomEntry);
					}
				}
				return list;
			}

			private int CalculateConflictScore(RoomEntry entry, HashSet<Level> avoidSourceLevels)
			{
				if (entry == null || (Object)(object)entry.SourceLevel == (Object)null || avoidSourceLevels == null || avoidSourceLevels.Count <= 0)
				{
					return 0;
				}
				return avoidSourceLevels.Contains(entry.SourceLevel) ? 1 : 0;
			}
		}

		private class MergedPools
		{
			public List<Level> SourceLevels = new List<Level>();

			public CategoryPool StartRooms = new CategoryPool();

			public CategoryPool NormalRooms = new CategoryPool();

			public CategoryPool PassageRooms = new CategoryPool();

			public CategoryPool DeadEndRooms = new CategoryPool();

			public CategoryPool ExtractionRooms = new CategoryPool();

			public CategoryPool SpecialRooms = new CategoryPool();
		}

		[HarmonyPatch(typeof(RunManager), "SetRunLevel")]
		private static class Patch_RunManager_SetRunLevel
		{
			private static bool Prefix(RunManager __instance)
			{
				try
				{
					if ((Object)(object)__instance == (Object)null || !CanForceMuseumBaseLevel())
					{
						return true;
					}
					if (!ForceMuseumBaseLevel("RunManager.SetRunLevel"))
					{
						return true;
					}
					return false;
				}
				catch (Exception ex)
				{
					if (LogSource != null)
					{
						LogSource.LogError((object)("SetRunLevel museum force failed\n" + ex));
					}
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(LevelGenerator), "Start")]
		private static class Patch_LevelGenerator_Start
		{
			private static void Prefix()
			{
				try
				{
					if (!((Object)(object)RunManager.instance == (Object)null) && ShouldForceMuseumBaseLevel(RunManager.instance.levelCurrent))
					{
						ForceMuseumBaseLevel("LevelGenerator.Start");
					}
				}
				catch (Exception ex)
				{
					if (LogSource != null)
					{
						LogSource.LogError((object)("LevelGenerator.Start museum force failed\n" + ex));
					}
				}
			}
		}

		[HarmonyPatch(typeof(LevelGenerator), "StartRoomGeneration")]
		private static class Patch_LevelGenerator_StartRoomGeneration
		{
			private static bool Prefix(LevelGenerator __instance, ref IEnumerator __result)
			{
				try
				{
					bool flag = (Object)(object)__instance != (Object)null && ShouldApply(__instance.Level);
					SetRoomMergedMapActiveProperty(flag);
					if (!flag)
					{
						return true;
					}
					__result = StartRoomGenerationOverride(__instance);
					return false;
				}
				catch (Exception ex)
				{
					if (LogSource != null)
					{
						LogSource.LogError((object)("StartRoomGeneration Prefix failed\n" + ex));
					}
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(LevelGenerator), "ModuleGeneration")]
		private static class Patch_LevelGenerator_ModuleGeneration
		{
			private static bool Prefix(LevelGenerator __instance, ref IEnumerator __result)
			{
				try
				{
					if ((Object)(object)__instance == (Object)null || !ShouldApply(__instance.Level))
					{
						return true;
					}
					__result = ModuleGenerationOverride(__instance);
					return false;
				}
				catch (Exception ex)
				{
					if (LogSource != null)
					{
						LogSource.LogError((object)("ModuleGeneration Prefix failed\n" + ex));
					}
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(ValuableDirector), "SetupHost")]
		private static class Patch_ValuableDirector_SetupHost
		{
			private static void Prefix()
			{
				try
				{
					Level baseLevel = (((Object)(object)LevelGenerator.Instance != (Object)null) ? LevelGenerator.Instance.Level : null);
					PrepareMergedValuablePresets(baseLevel);
				}
				catch (Exception ex)
				{
					if (LogSource != null)
					{
						LogSource.LogError((object)("PrepareMergedValuablePresets failed\n" + ex));
					}
				}
			}
		}

		[HarmonyPatch(typeof(RunManager), "UpdateSteamRichPresence")]
		private static class Patch_RunManager_UpdateSteamRichPresence
		{
			private static void Postfix(RunManager __instance)
			{
				UpdateRoomMergedMapActiveProperty();
				ApplyRichPresenceOverride(__instance);
			}
		}

		[HarmonyPatch(typeof(LoadingUI), "LevelAnimationStart")]
		private static class Patch_LoadingUI_LevelAnimationStart
		{
			private static void Postfix(LoadingUI __instance)
			{
				try
				{
					if ((Object)(object)__instance == (Object)null)
					{
						return;
					}
					Level val = (((Object)(object)LevelGenerator.Instance != (Object)null) ? LevelGenerator.Instance.Level : (((Object)(object)RunManager.instance != (Object)null) ? RunManager.instance.levelCurrent : null));
					if (!((Object)(object)val == (Object)null) && ShouldApplyClientVisuals(val))
					{
						LogLoadingGraphicCandidateNames(__instance, val);
						if ((Object)(object)CustomLoadingOverrideSprite != (Object)null)
						{
							ReplaceMatchedLoadingImage(__instance.loadingGraphic01, ResolveLoadingGraphicSprite(val, 1, __instance.loadingGraphic01));
							ReplaceMatchedLoadingImage(__instance.loadingGraphic02, ResolveLoadingGraphicSprite(val, 2, __instance.loadingGraphic02));
							ReplaceMatchedLoadingImage(__instance.loadingGraphic03, ResolveLoadingGraphicSprite(val, 3, __instance.loadingGraphic03));
						}
						if ((Object)(object)__instance.levelNameText != (Object)null)
						{
							((TMP_Text)__instance.levelNameText).text = GetMergedMapPresenceName();
						}
					}
				}
				catch (Exception ex)
				{
					if (LogSource != null)
					{
						LogSource.LogError((object)("Loading texture replace failed\n" + ex));
					}
				}
			}
		}

		[HarmonyPatch(typeof(LevelGenerator), "SpawnConnectObject")]
		private static class Patch_LevelGenerator_SpawnConnectObject
		{
			private static void Postfix(LevelGenerator __instance, Vector3 position, Vector3 rotation)
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (ShouldSanitizeMergedConnectObjects(__instance))
					{
						SanitizeSpawnedConnectObject(__instance, position);
					}
				}
				catch (Exception ex)
				{
					if (LogSource != null)
					{
						LogSource.LogError((object)("SpawnConnectObject sanitize failed\n" + ex));
					}
				}
			}
		}

		[HarmonyPatch(typeof(Module), "ModuleConnectionSetRPC")]
		private static class Patch_Module_ModuleConnectionSetRPC
		{
			private static void Postfix(Module __instance)
			{
				try
				{
					RemoveOuterDoorObjectsFromModule(__instance);
				}
				catch (Exception ex)
				{
					if (LogSource != null)
					{
						LogSource.LogError((object)("RemoveOuterDoorObjects failed\n" + ex));
					}
				}
			}
		}

		[CompilerGenerated]
		private sealed class <ModuleGenerationOverride>d__92 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public LevelGenerator generator;

			private MergedPools <pools>5__1;

			private Tile[,] <levelGrid>5__2;

			private int <width>5__3;

			private int <height>5__4;

			private RoomEntry[,] <plannedEntries>5__5;

			private Type[,] <plannedTypes>5__6;

			private CategoryUsage <normalUsage>5__7;

			private CategoryUsage <passageUsage>5__8;

			private CategoryUsage <deadEndUsage>5__9;

			private CategoryUsage <extractionUsage>5__10;

			private CategoryUsage <specialUsage>5__11;

			private int <x>5__12;

			private int <y>5__13;

			private Tile <tile>5__14;

			private Type <targetType>5__15;

			private HashSet<Level> <avoidSources>5__16;

			private CategoryPool <targetPool>5__17;

			private CategoryUsage <targetUsage>5__18;

			private RoomEntry <chosenEntry>5__19;

			private int <x>5__20;

			private int <y>5__21;

			private Tile <tile>5__22;

			private Vector3 <position>5__23;

			private Type <targetType>5__24;

			private Vector3 <rotation>5__25;

			private RoomEntry <chosenEntry>5__26;

			private CategoryPool <fallbackPool>5__27;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ModuleGenerationOverride>d__92(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || (uint)(num - 1) <= 1u)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<pools>5__1 = null;
				<levelGrid>5__2 = null;
				<plannedEntries>5__5 = null;
				<plannedTypes>5__6 = null;
				<normalUsage>5__7 = null;
				<passageUsage>5__8 = null;
				<deadEndUsage>5__9 = null;
				<extractionUsage>5__10 = null;
				<specialUsage>5__11 = null;
				<tile>5__14 = null;
				<avoidSources>5__16 = null;
				<targetPool>5__17 = null;
				<targetUsage>5__18 = null;
				<chosenEntry>5__19 = null;
				<tile>5__22 = null;
				<chosenEntry>5__26 = null;
				<fallbackPool>5__27 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_044d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0452: Unknown result type (might be due to invalid IL or missing references)
				//IL_046a: Unknown result type (might be due to invalid IL or missing references)
				//IL_046f: Unknown result type (might be due to invalid IL or missing references)
				//IL_048e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0493: Unknown result type (might be due to invalid IL or missing references)
				//IL_0498: Unknown result type (might be due to invalid IL or missing references)
				//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_04ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_0548: Unknown result type (might be due to invalid IL or missing references)
				//IL_054e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0554: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
				//IL_0203: Unknown result type (might be due to invalid IL or missing references)
				//IL_021b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0220: Unknown result type (might be due to invalid IL or missing references)
				//IL_0256: Unknown result type (might be due to invalid IL or missing references)
				//IL_0267: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
				bool result;
				try
				{
					switch (<>1__state)
					{
					default:
						result = false;
						goto end_IL_0000;
					case 0:
						<>1__state = -1;
						SetWaitingForSubCoroutine(generator, value: true);
						generator.State = (LevelState)5;
						<>1__state = -3;
						<pools>5__1 = BuildMergedPools(generator.Level);
						if (<pools>5__1.NormalRooms.UniqueCount <= 0)
						{
							<pools>5__1 = BuildCurrentLevelPools(generator.Level);
						}
						if (<pools>5__1.NormalRooms.UniqueCount <= 0)
						{
							result = false;
							break;
						}
						PassageAmountRef.Invoke(generator) = 0;
						<levelGrid>5__2 = LevelGridRef.Invoke(generator);
						if (<levelGrid>5__2 == null)
						{
							result = false;
							break;
						}
						<width>5__3 = generator.LevelWidth;
						<height>5__4 = generator.LevelHeight;
						<plannedEntries>5__5 = new RoomEntry[<width>5__3, <height>5__4];
						<plannedTypes>5__6 = new Type[<width>5__3, <height>5__4];
						<normalUsage>5__7 = new CategoryUsage();
						<passageUsage>5__8 = new CategoryUsage();
						<deadEndUsage>5__9 = new CategoryUsage();
						<extractionUsage>5__10 = new CategoryUsage();
						<specialUsage>5__11 = new CategoryUsage();
						<x>5__12 = 0;
						while (<x>5__12 < <width>5__3)
						{
							<y>5__13 = 0;
							while (<y>5__13 < <height>5__4)
							{
								<tile>5__14 = <levelGrid>5__2[<x>5__12, <y>5__13];
								if (<tile>5__14 != null && <tile>5__14.active)
								{
									<targetType>5__15 = ResolveTargetModuleType(generator, <levelGrid>5__2, <x>5__12, <y>5__13);
									<plannedTypes>5__6[<x>5__12, <y>5__13] = <targetType>5__15;
									<avoidSources>5__16 = CollectAdjacentSourceLevels(<plannedEntries>5__5, <width>5__3, <height>5__4, <x>5__12, <y>5__13);
									<targetPool>5__17 = GetPoolForType(<pools>5__1, <targetType>5__15);
									<targetUsage>5__18 = GetUsageForType(<targetType>5__15, <normalUsage>5__7, <passageUsage>5__8, <deadEndUsage>5__9, <extractionUsage>5__10, <specialUsage>5__11);
									<chosenEntry>5__19 = ChooseRoomEntry(<targetPool>5__17, <pools>5__1, <targetType>5__15, <avoidSources>5__16, <targetUsage>5__18);
									<plannedEntries>5__5[<x>5__12, <y>5__13] = <chosenEntry>5__19;
									<tile>5__14 = null;
									<avoidSources>5__16 = null;
									<targetPool>5__17 = null;
									<targetUsage>5__18 = null;
									<chosenEntry>5__19 = null;
								}
								<y>5__13++;
							}
							<x>5__12++;
						}
						OptimizePlannedEntries(<levelGrid>5__2, <plannedEntries>5__5, <plannedTypes>5__6, <pools>5__1, <width>5__3, <height>5__4);
						<x>5__20 = 0;
						goto IL_05b0;
					case 1:
						<>1__state = -3;
						<position>5__23 = new Vector3((float)<x>5__20 * LevelGenerator.ModuleWidth * LevelGenerator.TileSize - (float)(generator.LevelWidth / 2) * LevelGenerator.ModuleWidth * LevelGenerator.TileSize, 0f, (float)<y>5__21 * LevelGenerator.ModuleWidth * LevelGenerator.TileSize + LevelGenerator.ModuleWidth * LevelGenerator.TileSize / 2f);
						<targetType>5__24 = <plannedTypes>5__6[<x>5__20, <y>5__21];
						<rotation>5__25 = ResolveRotation(generator, <levelGrid>5__2, <x>5__20, <y>5__21, <targetType>5__24);
						<chosenEntry>5__26 = <plannedEntries>5__5[<x>5__20, <y>5__21];
						if (<chosenEntry>5__26 == null)
						{
							<fallbackPool>5__27 = GetPoolForType(<pools>5__1, <targetType>5__24);
							<chosenEntry>5__26 = ChooseRoomEntry(<fallbackPool>5__27, <pools>5__1, <targetType>5__24, null, null);
							<fallbackPool>5__27 = null;
						}
						if (<chosenEntry>5__26 != null && IsValidPrefabRef(<chosenEntry>5__26.PrefabRef))
						{
							SpawnMergedModule(generator, <levelGrid>5__2, <x>5__20, <y>5__21, <position>5__23, <rotation>5__25, <targetType>5__24, <chosenEntry>5__26);
							<tile>5__22 = null;
							<chosenEntry>5__26 = null;
						}
						goto IL_0574;
					case 2:
						{
							<>1__state = -3;
							<pools>5__1 = null;
							<levelGrid>5__2 = null;
							<plannedEntries>5__5 = null;
							<plannedTypes>5__6 = null;
							<normalUsage>5__7 = null;
							<passageUsage>5__8 = null;
							<deadEndUsage>5__9 = null;
							<extractionUsage>5__10 = null;
							<specialUsage>5__11 = null;
							<>m__Finally1();
							result = false;
							goto end_IL_0000;
						}
						IL_05b0:
						if (<x>5__20 < <width>5__3)
						{
							<y>5__21 = 0;
							goto IL_0586;
						}
						<>2__current = null;
						<>1__state = 2;
						result = true;
						goto end_IL_0000;
						IL_0574:
						<y>5__21++;
						goto IL_0586;
						IL_0586:
						if (<y>5__21 >= <height>5__4)
						{
							<x>5__20++;
							goto IL_05b0;
						}
						<tile>5__22 = <levelGrid>5__2[<x>5__20, <y>5__21];
						if (<tile>5__22 == null || !<tile>5__22.active)
						{
							goto IL_0574;
						}
						<>2__current = null;
						<>1__state = 1;
						result = true;
						goto end_IL_0000;
					}
					<>m__Finally1();
					end_IL_0000:;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
				return result;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				SetWaitingForSubCoroutine(generator, value: false);
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <StartRoomGenerationOverride>d__91 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public LevelGenerator generator;

			private MergedPools <pools>5__1;

			private CategoryPool <startPool>5__2;

			private PrefabRef <debugStartRoom>5__3;

			private RoomEntry <chosenEntry>5__4;

			private GameObject <roomObject>5__5;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <StartRoomGenerationOverride>d__91(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<pools>5__1 = null;
				<startPool>5__2 = null;
				<debugStartRoom>5__3 = null;
				<chosenEntry>5__4 = null;
				<roomObject>5__5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0166: Unknown result type (might be due to invalid IL or missing references)
				//IL_016b: Unknown result type (might be due to invalid IL or missing references)
				bool result;
				try
				{
					switch (<>1__state)
					{
					default:
						result = false;
						break;
					case 0:
						<>1__state = -1;
						SetWaitingForSubCoroutine(generator, value: true);
						generator.State = (LevelState)3;
						<>1__state = -3;
						<pools>5__1 = BuildMergedPools(generator.Level);
						<startPool>5__2 = ((RandomizeStartRooms != null && RandomizeStartRooms.Value && <pools>5__1.StartRooms.UniqueCount > 0) ? <pools>5__1.StartRooms : BuildCurrentLevelStartPool(generator.Level));
						if (<startPool>5__2 == null || <startPool>5__2.UniqueCount <= 0)
						{
							result = false;
						}
						else
						{
							<debugStartRoom>5__3 = GetDebugStartRoom(generator);
							<chosenEntry>5__4 = null;
							if (IsValidPrefabRef(<debugStartRoom>5__3))
							{
								<chosenEntry>5__4 = new RoomEntry(<debugStartRoom>5__3, generator.Level);
							}
							else
							{
								<chosenEntry>5__4 = <startPool>5__2.ChoosePreferDifferentSource(null, null, null);
							}
							if (<chosenEntry>5__4 != null && IsValidPrefabRef(<chosenEntry>5__4.PrefabRef))
							{
								<roomObject>5__5 = SpawnRoomObject(<chosenEntry>5__4.PrefabRef, Vector3.zero, Quaternion.identity);
								if ((Object)(object)<roomObject>5__5 != (Object)null && (Object)(object)generator.LevelParent != (Object)null)
								{
									<roomObject>5__5.transform.parent = generator.LevelParent.transform;
								}
								if (DebugLog != null && DebugLog.Value && LogSource != null)
								{
									LogSource.LogInfo((object)("Merged start room selected: " + <chosenEntry>5__4.PrefabRef.ResourcePath + " / SourceLevel=" + SafeLevelName(<chosenEntry>5__4.SourceLevel)));
								}
								<>2__current = null;
								<>1__state = 1;
								result = true;
								break;
							}
							result = false;
						}
						<>m__Finally1();
						break;
					case 1:
						<>1__state = -3;
						<pools>5__1 = null;
						<startPool>5__2 = null;
						<debugStartRoom>5__3 = null;
						<chosenEntry>5__4 = null;
						<roomObject>5__5 = null;
						<>m__Finally1();
						result = false;
						break;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
				return result;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				SetWaitingForSubCoroutine(generator, value: false);
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public const string PluginGuid = "REPOJP.AllMapMerge";

		public const string PluginName = "AllMapMerge";

		public const string PluginVersion = "4.0.0";

		internal const string MergedMapPresenceName = "AllMapMerge";

		internal const string MergedMapDiscordLargeImageKey = "allmapmerge";

		internal const string CustomLoadingOverrideFileName = "AllMapMerge.png";

		internal const string RoomPropertyMergedMapActiveKey = "REPOJP_AllMapMerge_Active";

		internal const string ForcedBaseLevelName = "museum";

		internal const string ForcedBaseLevelDisplayName = "Museum";

		internal static readonly string[] TargetLoadingTextureNames = new string[4] { "level arctic 01", "level wizard 01", "level museum 01", "level manor 01" };

		internal static readonly string[] SafeMergedVanillaLevelNames = new string[4] { "arctic", "wizard", "museum", "manor" };

		internal static Plugin Instance;

		internal static ManualLogSource LogSource;

		internal static Sprite CustomLoadingOverrideSprite;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> DangerousEnableAllMapsMergeIncludingModdedMapsCanBreakMaps;

		internal static ConfigEntry<bool> RandomizeStartRooms;

		internal static ConfigEntry<bool> FullyRandomIgnoreDifficultyTier;

		internal static ConfigEntry<bool> NoRepeatUntilPoolExhausted;

		internal static ConfigEntry<bool> PreferDifferentAdjacentSourceLevel;

		internal static ConfigEntry<int> AdjacencyImprovePasses;

		internal static ConfigEntry<bool> DebugLog;

		internal static ConfigEntry<bool> LogLoadingGraphicNames;

		internal static ConfigEntry<bool> RemoveOuterDoorObjects;

		internal static ConfigEntry<string> OuterDoorNameKeywords;

		internal static ConfigEntry<string> ExcludedRoomResourcePaths;

		private static readonly Dictionary<Level, List<LevelValuables>> OriginalValuablePresetsByLevel = new Dictionary<Level, List<LevelValuables>>();

		private static bool reflectionReady;

		private Harmony harmony;

		private static FieldRef<LevelGenerator, bool> WaitingForSubCoroutineRef;

		private static FieldRef<LevelGenerator, int> PassageAmountRef;

		private static FieldRef<LevelGenerator, Tile[,]> LevelGridRef;

		private static FieldRef<LevelGenerator, Vector3[]> ModuleRotationsRef;

		private static FieldRef<LevelGenerator, PrefabRef> DebugStartRoomRef;

		private static FieldRef<LevelGenerator, PrefabRef> DebugModuleRef;

		private static FieldRef<LevelGenerator, bool> DebugNormalRef;

		private static FieldRef<LevelGenerator, bool> DebugPassageRef;

		private static FieldRef<LevelGenerator, bool> DebugDeadEndRef;

		private static FieldRef<Module, int> GridXRef;

		private static FieldRef<Module, int> GridYRef;

		private static FieldRef<Module, bool> ConnectingTopRef;

		private static FieldRef<Module, bool> ConnectingRightRef;

		private static FieldRef<Module, bool> ConnectingBottomRef;

		private static FieldRef<Module, bool> ConnectingLeftRef;

		private static FieldRef<Module, bool> FirstRef;

		private static FieldInfo LevelLoadingGraphic01Field;

		private static FieldInfo LevelLoadingGraphic02Field;

		private static FieldInfo LevelLoadingGraphic03Field;

		private void Awake()
		{
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Expected O, but got Unknown
			try
			{
				Instance = this;
				LogSource = ((BaseUnityPlugin)this).Logger;
				((Component)this).transform.parent = null;
				((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
				Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable merged-map generation.AllMapMergeを有効化");
				DangerousEnableAllMapsMergeIncludingModdedMapsCanBreakMaps = ((BaseUnityPlugin)this).Config.Bind<bool>("Danger", "!!!DANGER_EnableAllMapsMergeIncludingModdedMaps_CanBreakMaps", false, "Recommended OFF.OFFが通常動作です ONにすると追加マップを含む全ての対象可能マップでマージを有効化し さらに追加マップを含む全ての対象可能マップの部屋をソースとして使用します 互換性崩壊や進行不能や表示崩れの可能性があります");
				RandomizeStartRooms = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RandomizeStartRooms", true, "Pick start rooms from the merged start-room pool.統合された開始部屋プールから開始部屋を選択");
				FullyRandomIgnoreDifficultyTier = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "FullyRandomIgnoreDifficultyTier", true, "Ignore difficulty tiers and merge 1/2/3 pools into one pool per category.難易度帯を無視して各カテゴリの1/2/3プールを1つに統合");
				NoRepeatUntilPoolExhausted = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "NoRepeatUntilPoolExhausted", false, "Do not repeat the same room in a category until its merged pool has been exhausted.カテゴリ内で統合プールを使い切るまで同じ部屋を再利用しない");
				PreferDifferentAdjacentSourceLevel = ((BaseUnityPlugin)this).Config.Bind<bool>("Generation", "PreferDifferentAdjacentSourceLevel", true, "Prefer a different source map than already planned adjacent rooms when possible.可能な限り隣接済み部屋と別の出典マップを優先");
				AdjacencyImprovePasses = ((BaseUnityPlugin)this).Config.Bind<int>("Generation", "AdjacencyImprovePasses", 2, new ConfigDescription("Improvement passes for reducing adjacent same-source rooms.隣接する同一出典部屋を減らす改善パス回数", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>()));
				DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugLog", false, "Enable debug logging.デバッグログを有効化");
				LogLoadingGraphicNames = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogLoadingGraphicNames", false, "Log loading graphic source names for replacement detection.差し替え判定用のローディング画像名ログを出力");
				RemoveOuterDoorObjects = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "RemoveOuterDoorObjects", true, "Disable likely outer-side door objects on non-connected module edges.非接続の外周面にある扉らしきオブジェクトを無効化");
				OuterDoorNameKeywords = ((BaseUnityPlugin)this).Config.Bind<string>("Compatibility", "OuterDoorNameKeywords", "door,gate,hatch", "Keywords used for detecting outer-side door objects.外周扉判定に使うキーワード");
				ExcludedRoomResourcePaths = ((BaseUnityPlugin)this).Config.Bind<string>("Filter", "ExcludedRoomResourcePaths", "", "Exclude specific resource paths. Separate with comma, semicolon, tab, or newline.除外するResourcePathを指定 カンマ セミコロン タブ 改行で区切り");
				reflectionReady = TryInitializeReflectionRefs();
				if (!reflectionReady)
				{
					LogSource.LogError((object)"Reflection initialization failed. Generation override disabled.");
				}
				LoadCustomLoadingOverrideSprite();
				harmony = new Harmony("REPOJP.AllMapMerge");
				harmony.PatchAll();
				LogSource.LogInfo((object)"AllMapMerge loaded for REPO 0.4.4 / version 4.0.0");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Awake failed\n" + ex));
			}
		}

		private static bool TryInitializeReflectionRefs()
		{
			try
			{
				WaitingForSubCoroutineRef = AccessTools.FieldRefAccess<LevelGenerator, bool>("waitingForSubCoroutine");
				PassageAmountRef = AccessTools.FieldRefAccess<LevelGenerator, int>("PassageAmount");
				LevelGridRef = AccessTools.FieldRefAccess<LevelGenerator, Tile[,]>("LevelGrid");
				ModuleRotationsRef = AccessTools.FieldRefAccess<LevelGenerator, Vector3[]>("ModuleRotations");
				DebugStartRoomRef = AccessTools.FieldRefAccess<LevelGenerator, PrefabRef>("DebugStartRoom");
				DebugModuleRef = AccessTools.FieldRefAccess<LevelGenerator, PrefabRef>("DebugModule");
				DebugNormalRef = AccessTools.FieldRefAccess<LevelGenerator, bool>("DebugNormal");
				DebugPassageRef = AccessTools.FieldRefAccess<LevelGenerator, bool>("DebugPassage");
				DebugDeadEndRef = AccessTools.FieldRefAccess<LevelGenerator, bool>("DebugDeadEnd");
				GridXRef = AccessTools.FieldRefAccess<Module, int>("GridX");
				GridYRef = AccessTools.FieldRefAccess<Module, int>("GridY");
				ConnectingTopRef = AccessTools.FieldRefAccess<Module, bool>("ConnectingTop");
				ConnectingRightRef = AccessTools.FieldRefAccess<Module, bool>("ConnectingRight");
				ConnectingBottomRef = AccessTools.FieldRefAccess<Module, bool>("ConnectingBottom");
				ConnectingLeftRef = AccessTools.FieldRefAccess<Module, bool>("ConnectingLeft");
				FirstRef = AccessTools.FieldRefAccess<Module, bool>("First");
				LevelLoadingGraphic01Field = AccessTools.Field(typeof(Level), "LoadingGraphic01");
				LevelLoadingGraphic02Field = AccessTools.Field(typeof(Level), "LoadingGraphic02");
				LevelLoadingGraphic03Field = AccessTools.Field(typeof(Level), "LoadingGraphic03");
				if ((LevelLoadingGraphic01Field == null || LevelLoadingGraphic02Field == null || LevelLoadingGraphic03Field == null) && LogSource != null)
				{
					LogSource.LogWarning((object)"Level.LoadingGraphic fields were not found. Loading image replacement will use current LoadingUI images as fallback.");
				}
				return true;
			}
			catch (Exception ex)
			{
				if (LogSource != null)
				{
					LogSource.LogError((object)("TryInitializeReflectionRefs failed\n" + ex));
				}
				return false;
			}
		}

		internal static bool ShouldApply(Level level)
		{
			if (!reflectionReady || Enabled == null || !Enabled.Value)
			{
				return false;
			}
			if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)level == (Object)null)
			{
				return false;
			}
			if (IsAlwaysExcludedLevel(level))
			{
				return false;
			}
			if (!IsGenerationAuthority())
			{
				return false;
			}
			return IsMergedSessionActiveForLevel(level);
		}

		internal static bool ShouldApplyClientVisuals(Level level)
		{
			if (Enabled == null || !Enabled.Value)
			{
				return false;
			}
			if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)level == (Object)null)
			{
				return false;
			}
			if (IsAlwaysExcludedLevel(level))
			{
				return false;
			}
			if (!PhotonNetwork.InRoom)
			{
				return IsMergedSessionActiveForLevel(level);
			}
			if (IsGenerationAuthority())
			{
				return IsMergedSessionActiveForLevel(level);
			}
			return IsRoomMergedMapActive();
		}

		internal static bool ShouldSanitizeMergedConnectObjects(LevelGenerator generator)
		{
			if ((Object)(object)generator == (Object)null)
			{
				return false;
			}
			Level val = generator.Level;
			if ((Object)(object)val == (Object)null && (Object)(object)RunManager.instance != (Object)null)
			{
				val = RunManager.instance.levelCurrent;
			}
			return ShouldApplyClientVisuals(val);
		}

		private static bool IsGenerationAuthority()
		{
			if (!PhotonNetwork.InRoom)
			{
				return true;
			}
			return PhotonNetwork.IsMasterClient;
		}

		private static bool IsRoomMergedMapActive()
		{
			if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null || ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties == null)
			{
				return false;
			}
			if (!((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"REPOJP_AllMapMerge_Active", out object value))
			{
				return false;
			}
			if (!(value is bool result))
			{
				if (value != null && bool.TryParse(value.ToString(), out var result2))
				{
					return result2;
				}
				return false;
			}
			return result;
		}

		private static bool IsMergedSessionActiveForLevel(Level level)
		{
			if ((Object)(object)level == (Object)null || IsAlwaysExcludedLevel(level))
			{
				return false;
			}
			if (!IsForcedBaseMuseumLevel(level))
			{
				return false;
			}
			return IsEligibleMergedSourceLevel(level);
		}

		private static void SetRoomMergedMapActiveProperty(bool active)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			if (!IsGenerationAuthority() || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null)
			{
				return;
			}
			bool flag = IsRoomMergedMapActive();
			if (flag != active)
			{
				Hashtable val = new Hashtable();
				val[(object)"REPOJP_AllMapMerge_Active"] = active;
				PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
				if (DebugLog != null && DebugLog.Value && LogSource != null)
				{
					LogSource.LogInfo((object)("Updated room merged-map flag: " + active));
				}
			}
		}

		private static void UpdateRoomMergedMapActiveProperty()
		{
			if (Enabled != null && Enabled.Value && !((Object)(object)RunManager.instance == (Object)null))
			{
				SetRoomMergedMapActiveProperty(IsMergedSessionActiveForLevel(RunManager.instance.levelCurrent));
			}
		}

		internal static bool ShouldOverrideRichPresence()
		{
			if (Enabled == null || !Enabled.Value)
			{
				return false;
			}
			if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)RunManager.instance.levelCurrent == (Object)null)
			{
				return false;
			}
			if (IsAlwaysExcludedLevel(RunManager.instance.levelCurrent))
			{
				return false;
			}
			if (!PhotonNetwork.InRoom)
			{
				return IsMergedSessionActiveForLevel(RunManager.instance.levelCurrent);
			}
			if (IsGenerationAuthority())
			{
				return IsMergedSessionActiveForLevel(RunManager.instance.levelCurrent);
			}
			return IsRoomMergedMapActive();
		}

		internal static string GetMergedMapPresenceName()
		{
			return "AllMapMerge";
		}

		internal static string GetCustomLoadingOverridePath()
		{
			string text = Path.Combine(Paths.ConfigPath, "AllMapMerge");
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			return Path.Combine(text, "AllMapMerge.png");
		}

		private static void LoadCustomLoadingOverrideSprite()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)CustomLoadingOverrideSprite != (Object)null)
			{
				try
				{
					if ((Object)(object)CustomLoadingOverrideSprite.texture != (Object)null)
					{
						Object.Destroy((Object)(object)CustomLoadingOverrideSprite.texture);
					}
					Object.Destroy((Object)(object)CustomLoadingOverrideSprite);
				}
				catch
				{
				}
				CustomLoadingOverrideSprite = null;
			}
			string customLoadingOverridePath = GetCustomLoadingOverridePath();
			if (!File.Exists(customLoadingOverridePath))
			{
				if (LogSource != null)
				{
					LogSource.LogInfo((object)("Custom loading override file not found: " + customLoadingOverridePath));
				}
				return;
			}
			try
			{
				byte[] array = File.ReadAllBytes(customLoadingOverridePath);
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				((Object)val).name = "AllMapMerge_LoadingOverride";
				if (!ImageConversion.LoadImage(val, array, false))
				{
					if (LogSource != null)
					{
						LogSource.LogError((object)("Failed to decode image: " + customLoadingOverridePath));
					}
					Object.Destroy((Object)(object)val);
					return;
				}
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Texture)val).filterMode = (FilterMode)1;
				CustomLoadingOverrideSprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				((Object)CustomLoadingOverrideSprite).name = "AllMapMerge_LoadingOverride_Sprite";
				if (LogSource != null)
				{
					LogSource.LogInfo((object)("Loaded custom loading override: " + customLoadingOverridePath));
				}
			}
			catch (Exception ex)
			{
				if (LogSource != null)
				{
					LogSource.LogError((object)("LoadCustomLoadingOverrideSprite failed\n" + ex));
				}
			}
		}

		internal static List<Level> CollectSourceLevels(Level baseLevel)
		{
			List<Level> result = new List<Level>();
			if ((Object)(object)RunManager.instance == (Object)null)
			{
				return result;
			}
			if (RunManager.instance.levels != null)
			{
				for (int i = 0; i < RunManager.instance.levels.Count; i++)
				{
					AddSourceLevelIfEligible(result, RunManager.instance.levels[i]);
				}
			}
			Level[] array = Resources.FindObjectsOfTypeAll<Level>();
			if (array != null)
			{
				for (int j = 0; j < array.Length; j++)
				{
					AddSourceLevelIfEligible(result, array[j]);
				}
			}
			AddSourceLevelIfEligible(result, baseLevel);
			AddSourceLevelIfEligible(result, RunManager.instance.levelCurrent);
			return result;
		}

		private static void AddSourceLevelIfEligible(List<Level> result, Level level)
		{
			if (result != null && IsEligibleMergedSourceLevel(level) && !result.Contains(level))
			{
				result.Add(level);
			}
		}

		private static bool IsAlwaysExcludedLevel(Level level)
		{
			if ((Object)(object)level == (Object)null)
			{
				return true;
			}
			if ((Object)(object)RunManager.instance == (Object)null)
			{
				return false;
			}
			if ((Object)(object)level == (Object)(object)RunManager.instance.levelMainMenu || (Object)(object)level == (Object)(object)RunManager.instance.levelSplashScreen || (Object)(object)level == (Object)(object)RunManager.instance.levelTutorial || (Object)(object)level == (Object)(object)RunManager.instance.levelLobbyMenu)
			{
				return true;
			}
			if ((Object)(object)level == (Object)(object)RunManager.instance.levelLobby || (Object)(object)level == (Object)(object)RunManager.instance.levelRecording)
			{
				return true;
			}
			if (IsLevelInList(level, RunManager.instance.levelArena))
			{
				return true;
			}
			if (IsLevelInList(level, RunManager.instance.levelShop))
			{
				return true;
			}
			return false;
		}

		private static bool IsLevelInList(Level level, List<Level> levels)
		{
			if ((Object)(object)level == (Object)null || levels == null)
			{
				return false;
			}
			for (int i = 0; i < levels.Count; i++)
			{
				if ((Object)(object)level == (Object)(object)levels[i])
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsForcedBaseMuseumLevel(Level level)
		{
			if ((Object)(object)level == (Object)null)
			{
				return false;
			}
			if (IsMuseumLoadingTexture(GetLevelLoadingGraphic(level, 1)))
			{
				return true;
			}
			if (IsMuseumLevelName(level.NarrativeName))
			{
				return true;
			}
			if (IsMuseumLevelName(((Object)level).name))
			{
				return true;
			}
			return false;
		}

		private static bool IsMuseumLoadingTexture(Sprite sprite)
		{
			if ((Object)(object)sprite == (Object)null)
			{
				return false;
			}
			if (IsMuseumLevelName(((Object)sprite).name))
			{
				return true;
			}
			if ((Object)(object)sprite.texture != (Object)null && IsMuseumLevelName(((Object)sprite.texture).name))
			{
				return true;
			}
			return false;
		}

		private static bool IsMuseumLevelName(string levelName)
		{
			if (string.IsNullOrWhiteSpace(levelName))
			{
				return false;
			}
			string text = NormalizeTextureName(levelName);
			text = text.Replace("level - ", string.Empty).Trim();
			text = text.Replace("level ", string.Empty).Trim();
			return text.IndexOf("museum", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static bool CanForceMuseumBaseLevel()
		{
			if (Enabled == null || !Enabled.Value)
			{
				return false;
			}
			if ((Object)(object)RunManager.instance == (Object)null)
			{
				return false;
			}
			if (!IsGenerationAuthority())
			{
				return false;
			}
			return true;
		}

		private static bool ShouldForceMuseumBaseLevel(Level level)
		{
			if (!CanForceMuseumBaseLevel())
			{
				return false;
			}
			if ((Object)(object)level == (Object)null)
			{
				return false;
			}
			if (IsAlwaysExcludedLevel(level))
			{
				return false;
			}
			if (IsForcedBaseMuseumLevel(level))
			{
				return false;
			}
			return HasMergeableRoomPools(level);
		}

		private static Level FindMuseumLevel()
		{
			if ((Object)(object)RunManager.instance == (Object)null)
			{
				return null;
			}
			Level val = FindMuseumLevelInList(RunManager.instance.levels);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Level[] array = Resources.FindObjectsOfTypeAll<Level>();
			if (array != null)
			{
				foreach (Level val2 in array)
				{
					if ((Object)(object)val2 != (Object)null && !IsAlwaysExcludedLevel(val2) && IsForcedBaseMuseumLevel(val2) && HasMergeableRoomPools(val2))
					{
						return val2;
					}
				}
			}
			return null;
		}

		private static Level FindMuseumLevelInList(List<Level> levels)
		{
			if (levels == null)
			{
				return null;
			}
			for (int i = 0; i < levels.Count; i++)
			{
				Level val = levels[i];
				if ((Object)(object)val != (Object)null && IsForcedBaseMuseumLevel(val) && HasMergeableRoomPools(val))
				{
					return val;
				}
			}
			return null;
		}

		private static bool ForceMuseumBaseLevel(string reason)
		{
			if (!CanForceMuseumBaseLevel())
			{
				return false;
			}
			Level levelCurrent = RunManager.instance.levelCurrent;
			Level val = FindMuseumLevel();
			if ((Object)(object)val == (Object)null)
			{
				if (LogSource != null)
				{
					LogSource.LogWarning((object)"Museum base level was not found. Vanilla level selection will be used.");
				}
				return false;
			}
			if ((Object)(object)levelCurrent == (Object)(object)val)
			{
				return true;
			}
			if (DebugLog != null && DebugLog.Value && LogSource != null)
			{
				LogSource.LogInfo((object)("Forced base level to " + SafeLevelName(val) + " from " + SafeLevelName(levelCurrent) + " / Reason=" + reason));
			}
			RunManager.instance.levelCurrent = val;
			return true;
		}

		private static bool IsEligibleMergedSourceLevel(Level level)
		{
			if ((Object)(object)level == (Object)null || (Object)(object)RunManager.instance == (Object)null)
			{
				return false;
			}
			if (IsAlwaysExcludedLevel(level))
			{
				return false;
			}
			if (!HasMergeableRoomPools(level))
			{
				return false;
			}
			if (DangerousEnableAllMapsMergeIncludingModdedMapsCanBreakMaps != null && DangerousEnableAllMapsMergeIncludingModdedMapsCanBreakMaps.Value)
			{
				return true;
			}
			return IsSafeTargetVanillaLevel(level);
		}

		private static bool IsSafeTargetVanillaLevel(Level level)
		{
			if ((Object)(object)level == (Object)null)
			{
				return false;
			}
			Sprite levelLoadingGraphic = GetLevelLoadingGraphic(level, 1);
			if (IsTargetLoadingTexture(levelLoadingGraphic))
			{
				return true;
			}
			if (IsSafeTargetVanillaLevelName(level.NarrativeName))
			{
				return true;
			}
			if (IsSafeTargetVanillaLevelName(((Object)level).name))
			{
				return true;
			}
			return false;
		}

		private static bool IsSafeTargetVanillaLevelName(string levelName)
		{
			if (string.IsNullOrWhiteSpace(levelName))
			{
				return false;
			}
			string text = NormalizeTextureName(levelName);
			text = text.Replace("level - ", string.Empty).Trim();
			text = text.Replace("level ", string.Empty).Trim();
			for (int i = 0; i < SafeMergedVanillaLevelNames.Length; i++)
			{
				if (string.Equals(text, SafeMergedVanillaLevelNames[i], StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static bool HasMergeableRoomPools(Level level)
		{
			if ((Object)(object)level == (Object)null)
			{
				return false;
			}
			if (HasPrefabRefList(level.StartRooms))
			{
				return true;
			}
			if (HasPrefabRefList(level.ModulesNormal1) || HasPrefabRefList(level.ModulesNormal2) || HasPrefabRefList(level.ModulesNormal3))
			{
				return true;
			}
			if (HasPrefabRefList(level.ModulesPassage1) || HasPrefabRefList(level.ModulesPassage2) || HasPrefabRefList(level.ModulesPassage3))
			{
				return true;
			}
			if (HasPrefabRefList(level.ModulesDeadEnd1) || HasPrefabRefList(level.ModulesDeadEnd2) || HasPrefabRefList(level.ModulesDeadEnd3))
			{
				return true;
			}
			if (HasPrefabRefList(level.ModulesExtraction1) || HasPrefabRefList(level.ModulesExtraction2) || HasPrefabRefList(level.ModulesExtraction3))
			{
				return true;
			}
			if (HasPrefabRefList(level.ModulesSpecial))
			{
				return true;
			}
			return false;
		}

		private static bool HasPrefabRefList(List<PrefabRef> prefabRefs)
		{
			if (prefabRefs == null || prefabRefs.Count <= 0)
			{
				return false;
			}
			for (int i = 0; i < prefabRefs.Count; i++)
			{
				PrefabRef prefabRef = prefabRefs[i];
				if (IsValidPrefabRef(prefabRef))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsValidPrefabRef(PrefabRef prefabRef)
		{
			if (prefabRef == null)
			{
				return false;
			}
			if (!prefabRef.IsValid())
			{
				return false;
			}
			if (string.IsNullOrEmpty(prefabRef.ResourcePath))
			{
				return false;
			}
			return true;
		}

		private static void PrepareMergedValuablePresets(Level baseLevel)
		{
			if ((Object)(object)baseLevel == (Object)null)
			{
				return;
			}
			CacheOriginalValuablePresets(baseLevel);
			if (!ShouldApply(baseLevel))
			{
				RestoreOriginalValuablePresets(baseLevel);
				return;
			}
			List<LevelValuables> list = BuildMergedValuablePresets(baseLevel);
			if (list.Count <= 0)
			{
				RestoreOriginalValuablePresets(baseLevel);
				return;
			}
			baseLevel.ValuablePresets = list;
			if (DebugLog != null && DebugLog.Value && LogSource != null)
			{
				LogSource.LogInfo((object)("Merged valuable preset count: " + list.Count));
			}
		}

		private static List<LevelValuables> BuildMergedValuablePresets(Level baseLevel)
		{
			List<LevelValuables> list = new List<LevelValuables>();
			List<Level> list2 = CollectValuableSourceLevels(baseLevel);
			for (int i = 0; i < list2.Count; i++)
			{
				List<LevelValuables> originalValuablePresets = GetOriginalValuablePresets(list2[i]);
				for (int j = 0; j < originalValuablePresets.Count; j++)
				{
					LevelValuables val = originalValuablePresets[j];
					if ((Object)(object)val != (Object)null)
					{
						list.Add(val);
					}
				}
			}
			if (DebugLog != null && DebugLog.Value && LogSource != null)
			{
				LogSource.LogInfo((object)("Merged valuable source level count: " + list2.Count));
			}
			return list;
		}

		internal static List<Level> CollectValuableSourceLevels(Level baseLevel)
		{
			List<Level> result = new List<Level>();
			if ((Object)(object)RunManager.instance == (Object)null)
			{
				return result;
			}
			if (RunManager.instance.levels != null)
			{
				for (int i = 0; i < RunManager.instance.levels.Count; i++)
				{
					AddValuableSourceLevelIfEligible(result, RunManager.instance.levels[i]);
				}
			}
			Level[] array = Resources.FindObjectsOfTypeAll<Level>();
			if (array != null)
			{
				for (int j = 0; j < array.Length; j++)
				{
					AddValuableSourceLevelIfEligible(result, array[j]);
				}
			}
			AddValuableSourceLevelIfEligible(result, baseLevel);
			AddValuableSourceLevelIfEligible(result, RunManager.instance.levelCurrent);
			return result;
		}

		private static void AddValuableSourceLevelIfEligible(List<Level> result, Level level)
		{
			if (result != null && !((Object)(object)level == (Object)null) && IsEligibleMergedSourceLevel(level) && HasAnyValuablePresets(level) && !result.Contains(level))
			{
				result.Add(level);
			}
		}

		private static bool HasAnyValuablePresets(Level level)
		{
			List<LevelValuables> originalValuablePresets = GetOriginalValuablePresets(level);
			if (originalValuablePresets == null || originalValuablePresets.Count <= 0)
			{
				return false;
			}
			for (int i = 0; i < originalValuablePresets.Count; i++)
			{
				if ((Object)(object)originalValuablePresets[i] != (Object)null)
				{
					return true;
				}
			}
			return false;
		}

		private static void CacheOriginalValuablePresets(Level level)
		{
			if (!((Object)(object)level == (Object)null) && !OriginalValuablePresetsByLevel.ContainsKey(level))
			{
				OriginalValuablePresetsByLevel[level] = CloneValuablePresetList(level.ValuablePresets);
			}
		}

		private static List<LevelValuables> GetOriginalValuablePresets(Level level)
		{
			if ((Object)(object)level == (Object)null)
			{
				return new List<LevelValuables>();
			}
			CacheOriginalValuablePresets(level);
			if (!OriginalValuablePresetsByLevel.TryGetValue(level, out var value) || value == null)
			{
				return new List<LevelValuables>();
			}
			return CloneValuablePresetList(value);
		}

		private static void RestoreOriginalValuablePresets(Level level)
		{
			if (!((Object)(object)level == (Object)null) && OriginalValuablePresetsByLevel.TryGetValue(level, out var value) && value != null)
			{
				level.ValuablePresets = CloneValuablePresetList(value);
			}
		}

		private static List<LevelValuables> CloneValuablePresetList(List<LevelValuables> source)
		{
			List<LevelValuables> list = new List<LevelValuables>();
			if (source == null)
			{
				return list;
			}
			for (int i = 0; i < source.Count; i++)
			{
				if ((Object)(object)source[i] != (Object)null)
				{
					list.Add(source[i]);
				}
			}
			return list;
		}

		private static MergedPools BuildMergedPools(Level baseLevel)
		{
			List<Level> list = CollectSourceLevels(baseLevel);
			HashSet<string> excludedPaths = ParseExcludedPaths();
			MergedPools mergedPools = new MergedPools();
			mergedPools.SourceLevels = list;
			for (int i = 0; i < list.Count; i++)
			{
				Level val = list[i];
				AddListToCategoryPool(mergedPools.StartRooms, val, val.StartRooms, excludedPaths, allowDuplicatePaths: false);
			}
			for (int j = 0; j < list.Count; j++)
			{
				Level val2 = list[j];
				if (FullyRandomIgnoreDifficultyTier != null && FullyRandomIgnoreDifficultyTier.Value)
				{
					AddListToCategoryPool(mergedPools.NormalRooms, val2, val2.ModulesNormal1, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.NormalRooms, val2, val2.ModulesNormal2, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.NormalRooms, val2, val2.ModulesNormal3, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.PassageRooms, val2, val2.ModulesPassage1, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.PassageRooms, val2, val2.ModulesPassage2, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.PassageRooms, val2, val2.ModulesPassage3, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.DeadEndRooms, val2, val2.ModulesDeadEnd1, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.DeadEndRooms, val2, val2.ModulesDeadEnd2, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.DeadEndRooms, val2, val2.ModulesDeadEnd3, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.ExtractionRooms, val2, val2.ModulesExtraction1, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.ExtractionRooms, val2, val2.ModulesExtraction2, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.ExtractionRooms, val2, val2.ModulesExtraction3, excludedPaths, allowDuplicatePaths: false);
				}
				else
				{
					AddListToCategoryPool(mergedPools.NormalRooms, val2, val2.ModulesNormal1, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.PassageRooms, val2, val2.ModulesPassage1, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.DeadEndRooms, val2, val2.ModulesDeadEnd1, excludedPaths, allowDuplicatePaths: false);
					AddListToCategoryPool(mergedPools.ExtractionRooms, val2, val2.ModulesExtraction1, excludedPaths, allowDuplicatePaths: false);
				}
				AddListToCategoryPool(mergedPools.SpecialRooms, val2, val2.ModulesSpecial, excludedPaths, allowDuplicatePaths: false);
			}
			if (DebugLog != null && DebugLog.Value && LogSource != null)
			{
				LogSource.LogInfo((object)("Merged source level count: " + list.Count));
				LogSource.LogInfo((object)("MergedStartRooms: " + mergedPools.StartRooms.UniqueCount));
				LogSource.LogInfo((object)("MergedNormalRooms: " + mergedPools.NormalRooms.UniqueCount));
				LogSource.LogInfo((object)("MergedPassageRooms: " + mergedPools.PassageRooms.UniqueCount));
				LogSource.LogInfo((object)("MergedDeadEndRooms: " + mergedPools.DeadEndRooms.UniqueCount));
				LogSource.LogInfo((object)("MergedExtractionRooms: " + mergedPools.ExtractionRooms.UniqueCount));
				LogSource.LogInfo((object)("MergedSpecialRooms: " + mergedPools.SpecialRooms.UniqueCount));
			}
			return mergedPools;
		}

		private static void AddListToCategoryPool(CategoryPool pool, Level sourceLevel, List<PrefabRef> sourceList, HashSet<string> excludedPaths, bool allowDuplicatePaths)
		{
			if (pool == null || (Object)(object)sourceLevel == (Object)null || sourceList == null)
			{
				return;
			}
			for (int i = 0; i < sourceList.Count; i++)
			{
				PrefabRef val = sourceList[i];
				if (IsValidPrefabRef(val))
				{
					string resourcePath = val.ResourcePath;
					if ((excludedPaths == null || !excludedPaths.Contains(resourcePath)) && (allowDuplicatePaths || !pool.ContainsResourcePath(resourcePath)))
					{
						pool.Add(new RoomEntry(val, sourceLevel));
					}
				}
			}
		}

		[IteratorStateMachine(typeof(<StartRoomGenerationOverride>d__91))]
		internal static IEnumerator StartRoomGenerationOverride(LevelGenerator generator)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <StartRoomGenerationOverride>d__91(0)
			{
				generator = generator
			};
		}

		[IteratorStateMachine(typeof(<ModuleGenerationOverride>d__92))]
		internal static IEnumerator ModuleGenerationOverride(LevelGenerator generator)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ModuleGenerationOverride>d__92(0)
			{
				generator = generator
			};
		}

		private static void SetWaitingForSubCoroutine(LevelGenerator generator, bool value)
		{
			if (!((Object)(object)generator == (Object)null) && WaitingForSubCoroutineRef != null)
			{
				WaitingForSubCoroutineRef.Invoke(generator) = value;
			}
		}

		private static PrefabRef GetDebugStartRoom(LevelGenerator generator)
		{
			if ((Object)(object)generator == (Object)null || DebugStartRoomRef == null)
			{
				return null;
			}
			return DebugStartRoomRef.Invoke(generator);
		}

		private static PrefabRef GetDebugModule(LevelGenerator generator)
		{
			if ((Object)(object)generator == (Object)null || DebugModuleRef == null)
			{
				return null;
			}
			return DebugModuleRef.Invoke(generator);
		}

		private static bool GetDebugNormal(LevelGenerator generator)
		{
			return (Object)(object)generator != (Object)null && DebugNormalRef != null && DebugNormalRef.Invoke(generator);
		}

		private static bool GetDebugPassage(LevelGenerator generator)
		{
			return (Object)(object)generator != (Object)null && DebugPassageRef != null && DebugPassageRef.Invoke(generator);
		}

		private static bool GetDebugDeadEnd(LevelGenerator generator)
		{
			return (Object)(object)generator != (Object)null && DebugDeadEndRef != null && DebugDeadEndRef.Invoke(generator);
		}

		private static void OptimizePlannedEntries(Tile[,] levelGrid, RoomEntry[,] plannedEntries, Type[,] plannedTypes, MergedPools pools, int width, int height)
		{
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			if (PreferDifferentAdjacentSourceLevel == null || !PreferDifferentAdjacentSourceLevel.Value)
			{
				return;
			}
			int num = ((AdjacencyImprovePasses != null) ? AdjacencyImprovePasses.Value : 0);
			if (num <= 0)
			{
				return;
			}
			for (int i = 0; i < num; i++)
			{
				bool flag = false;
				for (int j = 0; j < width; j++)
				{
					for (int k = 0; k < height; k++)
					{
						Tile val = levelGrid[j, k];
						if (val == null || !val.active)
						{
							continue;
						}
						RoomEntry roomEntry = plannedEntries[j, k];
						if (roomEntry == null)
						{
							continue;
						}
						HashSet<Level> hashSet = CollectAdjacentSourceLevels(plannedEntries, width, height, j, k);
						if (hashSet.Count > 0 && (!((Object)(object)roomEntry.SourceLevel != (Object)null) || hashSet.Contains(roomEntry.SourceLevel)))
						{
							RoomEntry roomEntry2 = GetPoolForType(pools, plannedTypes[j, k])?.ChoosePreferDifferentSource(hashSet, null, roomEntry);
							if (roomEntry2 != null && IsValidPrefabRef(roomEntry2.PrefabRef) && roomEntry2 != roomEntry && !((Object)(object)roomEntry2.SourceLevel == (Object)(object)roomEntry.SourceLevel))
							{
								plannedEntries[j, k] = roomEntry2;
								flag = true;
							}
						}
					}
				}
				if (!flag)
				{
					break;
				}
			}
		}

		private static HashSet<Level> CollectAdjacentSourceLevels(RoomEntry[,] plannedEntries, int width, int height, int x, int y)
		{
			HashSet<Level> result = new HashSet<Level>();
			AddPlannedNeighborSourceLevel(plannedEntries, width, height, x, y - 1, result);
			AddPlannedNeighborSourceLevel(plannedEntries, width, height, x - 1, y, result);
			AddPlannedNeighborSourceLevel(plannedEntries, width, height, x + 1, y, result);
			AddPlannedNeighborSourceLevel(plannedEntries, width, height, x, y + 1, result);
			return result;
		}

		private static void AddPlannedNeighborSourceLevel(RoomEntry[,] plannedEntries, int width, int height, int x, int y, HashSet<Level> result)
		{
			if (plannedEntries != null && result != null && x >= 0 && x < width && y >= 0 && y < height)
			{
				RoomEntry roomEntry = plannedEntries[x, y];
				if (roomEntry != null && !((Object)(object)roomEntry.SourceLevel == (Object)null))
				{
					result.Add(roomEntry.SourceLevel);
				}
			}
		}

		private static CategoryPool GetPoolForType(MergedPools pools, Type targetType)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Invalid comparison between Unknown and I4
			if (pools == null)
			{
				return null;
			}
			if ((int)targetType == 1)
			{
				return pools.PassageRooms;
			}
			if ((int)targetType == 2)
			{
				return pools.DeadEndRooms;
			}
			if ((int)targetType == 3)
			{
				return pools.ExtractionRooms;
			}
			if ((int)targetType == 4)
			{
				return pools.SpecialRooms;
			}
			return pools.NormalRooms;
		}

		private static CategoryUsage GetUsageForType(Type targetType, CategoryUsage normalUsage, CategoryUsage passageUsage, CategoryUsage deadEndUsage, CategoryUsage extractionUsage, CategoryUsage specialUsage)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Invalid comparison between Unknown and I4
			if ((int)targetType == 1)
			{
				return passageUsage;
			}
			if ((int)targetType == 2)
			{
				return deadEndUsage;
			}
			if ((int)targetType == 3)
			{
				return extractionUsage;
			}
			if ((int)targetType == 4)
			{
				return specialUsage;
			}
			return normalUsage;
		}

		private static Type ResolveTargetModuleType(LevelGenerator generator, Tile[,] levelGrid, int x, int y)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: 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_0042: Invalid comparison between Unknown and I4
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Invalid comparison between Unknown and I4
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Invalid comparison between Unknown and I4
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			Tile val = levelGrid[x, y];
			if (val == null)
			{
				return (Type)0;
			}
			if (!GetDebugNormal(generator) && !GetDebugPassage(generator) && !GetDebugDeadEnd(generator))
			{
				if ((int)val.type == 3)
				{
					return (Type)3;
				}
				if ((int)val.type == 2)
				{
					return (Type)2;
				}
				if ((int)val.type == 4)
				{
					return (Type)4;
				}
			}
			if (GetDebugDeadEnd(generator))
			{
				return (Type)2;
			}
			if (!GetDebugNormal(generator) && (GetDebugPassage(generator) || PassageAmountRef.Invoke(generator) < generator.Level.PassageMaxAmount))
			{
				bool flag = GetDebugPassage(generator) || (GridCheckActive(generator, levelGrid, x, y + 1) && (GridCheckActive(generator, levelGrid, x, y - 1) || val.first) && !GridCheckActive(generator, levelGrid, x + 1, y) && !GridCheckActive(generator, levelGrid, x - 1, y));
				bool flag2 = !val.first && GridCheckActive(generator, levelGrid, x + 1, y) && GridCheckActive(generator, levelGrid, x - 1, y) && !GridCheckActive(generator, levelGrid, x, y + 1) && !GridCheckActive(generator, levelGrid, x, y - 1);
				if (flag || flag2)
				{
					PassageAmountRef.Invoke(generator) = PassageAmountRef.Invoke(generator) + 1;
					return (Type)1;
				}
			}
			return (Type)0;
		}

		private static Vector3 ResolveRotation(LevelGenerator generator, Tile[,] levelGrid, int x, int y, Type targetType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Invalid comparison between Unknown and I4
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Invalid comparison between Unknown and I4
			//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_0057: 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_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			if ((int)targetType == 3 || (int)targetType == 2 || (int)targetType == 4)
			{
				if (GridCheckActive(generator, levelGrid, x, y - 1))
				{
					return Vector3.zero;
				}
				if (GridCheckActive(generator, levelGrid, x - 1, y))
				{
					return new Vector3(0f, 90f, 0f);
				}
				if (GridCheckActive(generator, levelGrid, x, y + 1))
				{
					return new Vector3(0f, 180f, 0f);
				}
				if (GridCheckActive(generator, levelGrid, x + 1, y))
				{
					return new Vector3(0f, -90f, 0f);
				}
				return Vector3.zero;
			}
			if ((int)targetType == 1)
			{
				bool flag = GridCheckActive(generator, levelGrid, x, y + 1) && (GridCheckActive(generator, levelGrid, x, y - 1) || levelGrid[x, y].first) && !GridCheckActive(generator, levelGrid, x + 1, y) && !GridCheckActive(generator, levelGrid, x - 1, y);
				bool flag2 = !levelGrid[x, y].first && GridCheckActive(generator, levelGrid, x + 1, y) && GridCheckActive(generator, levelGrid, x - 1, y) && !GridCheckActive(generator, levelGrid, x, y + 1) && !GridCheckActive(generator, levelGrid, x, y - 1);
				if (flag)
				{
					return (Vector3)((Random.Range(0, 100) < 50) ? new Vector3(0f, 180f, 0f) : Vector3.zero);
				}
				if (flag2)
				{
					return (Random.Range(0, 100) < 50) ? new Vector3(0f, -90f, 0f) : new Vector3(0f, 90f, 0f);
				}
			}
			Vector3[] array = ModuleRotationsRef.Invoke(generator);
			if (array != null && array.Length != 0)
			{
				return array[Random.Range(0, array.Length)];
			}
			return Vector3.zero;
		}

		private static RoomEntry ChooseRoomEntry(CategoryPool targetPool, MergedPools pools, Type targetType, HashSet<Level> avoidSources, CategoryUsage usage)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			RoomEntry roomEntry = targetPool?.ChoosePreferDifferentSource(avoidSources, usage, null);
			if (roomEntry != null)
			{
				return roomEntry;
			}
			if ((int)targetType != 0 && pools != null && pools.NormalRooms != null && pools.NormalRooms.UniqueCount > 0)
			{
				return pools.NormalRooms.ChoosePreferDifferentSource(avoidSources, usage, null);
			}
			return null;
		}

		private static void SpawnMergedModule(LevelGenerator generator, Tile[,] levelGrid, int x, int y, Vector3 position, Vector3 rotation, Type targetType, RoomEntry entry)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			if (entry == null || !IsValidPrefabRef(entry.PrefabRef))
			{
				return;
			}
			PrefabRef debugModule = GetDebugModule(generator);
			PrefabRef val = (IsValidPrefabRef(debugModule) ? debugModule : entry.PrefabRef);
			GameObject val2 = SpawnRoomObject(val, position, Quaternion.Euler(rotation));
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			if ((Object)(object)generator.LevelParent != (Object)null)
			{
				val2.transform.parent = generator.LevelParent.transform;
			}
			Module component = val2.GetComponent<Module>();
			if ((Object)(object)component == (Object)null)
			{
				if (DebugLog != null && DebugLog.Value && LogSource != null)
				{
					LogSource.LogWarning((object)("Spawned merged room has no Module component: " + val.ResourcePath));
				}
				return;
			}
			GridXRef.Invoke(component) = x;
			GridYRef.Invoke(component) = y;
			levelGrid[x, y].type = targetType;
			bool first = levelGrid[x, y].first;
			bool flag = GridCheckActive(generator, levelGrid, x, y + 1);
			bool flag2 = GridCheckActive(generator, levelGrid, x, y - 1) || first;
			bool flag3 = GridCheckActive(generator, levelGrid, x + 1, y);
			bool flag4 = GridCheckActive(generator, levelGrid, x - 1, y);
			component.ModuleConnectionSet(flag, flag2, flag3, flag4, first);
			if (DebugLog != null && DebugLog.Value && LogSource != null)
			{
				LogSource.LogInfo((object)("Merged room selected: " + val.ResourcePath + " / SourceLevel=" + SafeLevelName(entry.SourceLevel) + " / Type=" + ((object)(Type)(ref targetType)).ToString() + " / Grid=(" + x + "," + y + ")"));
			}
		}

		private static GameObject SpawnRoomObject(PrefabRef prefabRef, Vector3 position, Quaternion rotation)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (!IsValidPrefabRef(prefabRef))
			{
				return null;
			}
			if ((Object)(object)GameManager.instance == (Object)null || GameManager.instance.gameMode == 0)
			{
				GameObject prefab = prefabRef.Prefab;
				if ((Object)(object)prefab == (Object)null)
				{
					return null;
				}
				return Object.Instantiate<GameObject>(prefab, position, rotation);
			}
			return PhotonNetwork.InstantiateRoomObject(prefabRef.ResourcePath, position, rotation, (byte)0, (object[])null);
		}

		private static bool GridCheckActive(LevelGenerator generator, Tile[,] levelGrid, int x, int y)
		{
			if ((Object)(object)generator == (Object)null || levelGrid == null)
			{
				return false;
			}
			if (x < 0 || x >= generator.LevelWidth || y < 0 || y >= generator.LevelHeight)
			{
				return false;
			}
			return levelGrid[x, y]?.active ?? false;
		}

		private static CategoryPool BuildCurrentLevelStartPool(Level level)
		{
			CategoryPool categoryPool = new CategoryPool();
			HashSet<string> excludedPaths = ParseExcludedPaths();
			AddListToCategoryPool(categoryPool, level, ((Object)(object)level != (Object)null) ? level.StartRooms : null, excludedPaths, allowDuplicatePaths: false);
			return categoryPool;
		}

		private static MergedPools BuildCurrentLevelPools(Level level)
		{
			MergedPools mergedPools = new MergedPools();
			HashSet<string> excludedPaths = ParseExcludedPaths();
			if ((Object)(object)level == (Object)null)
			{
				return mergedPools;
			}
			mergedPools.SourceLevels.Add(level);
			AddListToCategoryPool(mergedPools.StartRooms, level, level.StartRooms, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.NormalRooms, level, level.ModulesNormal1, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.NormalRooms, level, level.ModulesNormal2, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.NormalRooms, level, level.ModulesNormal3, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.PassageRooms, level, level.ModulesPassage1, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.PassageRooms, level, level.ModulesPassage2, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.PassageRooms, level, level.ModulesPassage3, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.DeadEndRooms, level, level.ModulesDeadEnd1, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.DeadEndRooms, level, level.ModulesDeadEnd2, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.DeadEndRooms, level, level.ModulesDeadEnd3, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.ExtractionRooms, level, level.ModulesExtraction1, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.ExtractionRooms, level, level.ModulesExtraction2, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.ExtractionRooms, level, level.ModulesExtraction3, excludedPaths, allowDuplicatePaths: false);
			AddListToCategoryPool(mergedPools.SpecialRooms, level, level.ModulesSpecial, excludedPaths, allowDuplicatePaths: false);
			return mergedPools;
		}

		private static HashSet<string> ParseExcludedPaths()
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			if (ExcludedRoomResourcePaths == null)
			{
				return hashSet;
			}
			string value = ExcludedRoomResourcePaths.Value;
			if (string.IsNullOrWhiteSpace(value))
			{
				return hashSet;
			}
			string[] array = value.Split(new char[5] { ',', ';', '\r', '\n', '\t' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text in array)
			{
				if (!string.IsNullOrWhiteSpace(text))
				{
					hashSet.Add(text.Trim());
				}
			}
			return hashSet;
		}

		private static string SafeLevelName(Level level)
		{
			if ((Object)(object)level == (Object)null)
			{
				return "null";
			}
			return ((Object)level).name;
		}

		private static void RemoveOuterDoorObjectsFromModule(Module module)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			if (RemoveOuterDoorObjects == null || !RemoveOuterDoorObjects.Value || (Object)(object)module == (Object)null)
			{
				return;
			}
			Level level = (((Object)(object)RunManager.instance != (Object)null) ? RunManager.instance.levelCurrent : null);
			if (!ShouldApplyClientVisuals(level))
			{
				return;
			}
			EnsureClosedSideBlockers(module);
			ModulePropSwitch[] componentsInChildren = ((Component)module).GetComponentsInChildren<ModulePropSwitch>(true);
			if (componentsInChildren == null || componentsInChildren.Length == 0)
			{
				EnsureClosedSideBlockers(module);
				return;
			}
			foreach (ModulePropSwitch val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !IsConnectionSideOpen(module, val.ConnectionSide))
				{
					DisableOuterDoorObjects(val.NotConnectedParent, module, val.ConnectionSide);
				}
			}
			EnsureClosedSideBlockers(module);
		}

		private static void EnsureClosedSideBlockers(Module module)
		{
			if (!((Object)(object)module == (Object)null))
			{
				if (!GetModuleConnectingTop(module))
				{
					EnsureClosedSideBlocker(module, (Connection)0);
				}
				if (!GetModuleConnectingRight(module))
				{
					EnsureClosedSideBlocker(module, (Connection)1);
				}
				if (!GetModuleConnectingBottom(module))
				{
					EnsureClosedSideBlocker(module, (Connection)2);
				}
				if (!GetModuleConnectingLeft(module))
				{
					EnsureClosedSideBlocker(module, (Connection)3);
				}
			}
		}

		private static bool IsConnectionSideOpen(Module module, Connection side)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected I4, but got Unknown
			if ((Object)(object)module == (Object)null)
			{
				return false;
			}
			return (int)side switch
			{
				0 => GetModuleConnectingTop(module), 
				1 => GetModuleConnectingRight(module), 
				2 => GetModuleConnectingBottom(module), 
				3 => GetModuleConnectingLeft(module), 
				_ => false, 
			};
		}

		private static bool GetModuleConnectingTop(Module module)
		{
			return (Object)(object)module != (Object)null && ConnectingTopRef != null && ConnectingTopRef.Invoke(module);
		}

		private static bool GetModuleConnectingRight(Module module)
		{
			return (Object)(object)module != (Object)null && ConnectingRightRef != null && ConnectingRightRef.Invoke(module);
		}

		private static bool GetModuleConnectingBottom(Module module)
		{
			return (Object)(object)module != (Object)null && ConnectingBottomRef != null && ConnectingBottomRef.Invoke(module);
		}

		private static bool GetModuleConnectingLeft(Module module)
		{
			return (Object)(object)module != (Object)null && ConnectingLeftRef != null && ConnectingLeftRef.Invoke(module);
		}

		private static bool GetModuleFirst(Module module)
		{
			return (Object)(object)module != (Object)null && FirstRef != null && FirstRef.Invoke(module);
		}

		private static void EnsureClosedSideBlocker(Module module, Connection side)
		{
			//IL_0119: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected I4, but got Unknown
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)module == (Object)null)
			{
				return;
			}
			LevelGenerator instance = LevelGenerator.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Level val = (((Object)(object)instance.Level != (Object)null) ? instance.Level : (((Object)(object)RunManager.instance != (Object)null) ? RunManager.instance.levelCurrent : null));
			if ((Object)(object)val == (Object)null || !IsValidPrefabRef(val.BlockObject))
			{
				return;
			}
			Tile[,] array = LevelGridRef.Invoke(instance);
			if (array == null)
			{
				return;
			}
			int num = GridXRef.Invoke(module);
			int num2 = GridYRef.Invoke(module);
			if (num < 0 || num >= instance.LevelWidth || num2 < 0 || num2 >= instance.LevelHeight)
			{
				return;
			}
			Tile val2 = array[num, num2];
			if (val2 == null)
			{
				return;
			}
			float num3 = LevelGenerator.ModuleWidth * LevelGenerator.TileSize;
			Vector3 position = ((Component)module).transform.position;
			Vector3 val3 = position;
			Vector3 zero = Vector3.zero;
			switch ((int)side)
			{
			default:
				return;
			case 0:
				val3 += new Vector3(0f, 0f, num3 / 2f);
				((Vector3)(ref zero))..ctor(0f, 180f, 0f);
				break;
			case 1:
				val3 += new Vector3(num3 / 2f, 0f, 0f);
				((Vector3)(ref zero))..ctor(0f, -90f, 0f);
				break;
			case 2:
				if (GetModuleFirst(module))
				{
					return;
				}
				val3 += new Vector3(0f, 0f, (0f - num3) / 2f);
				zero = Vector3.zero;
				break;
			case 3:
				val3 += new Vector3((0f - num3) / 2f, 0f, 0f);
				((Vector3)(ref zero))..ctor(0f, 90f, 0f);
				break;
			}
			if (HasNearbyBlocker(instance, val3, val.BlockObject.PrefabName))
			{
				return;
			}
			GameObject val4 = null;
			if ((Object)(object)GameManager.instance == (Object)null || GameManager.instance.gameMode == 0)
			{
				GameObject prefab = val.BlockObject.Prefab;
				if ((Object)(object)prefab != (Object)null)
				{
					val4 = Object.Instantiate<GameObject>(prefab, val3, Quaternion.Euler(zero));
				}
			}
			else if (PhotonNetwork.IsMasterClient)
			{
				val4 = PhotonNetwork.InstantiateRoomObject(val.BlockObject.ResourcePath, val3, Quaternion.Euler(zero), (byte)0, (object[])null);
			}
			if (!((Object)(object)val4 == (Object)null) && (Object)(object)instance.LevelParent != (Object)null)
			{
				val4.transform.parent = instance.LevelParent.transform;
			}
		}

		private static bool HasNearbyBlocker(LevelGenerator generator, Vector3 position, string blockObjectName)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)generator == (Object)null || (Object)(object)generator.LevelParent == (Object)null)
			{
				return false;
			}
			string text = NormalizePrefabName(blockObjectName);
			Transform transform = generator.LevelParent.transform;
			for (int i = 0; i < transform.childCount; i++)
			{
				Transform child = transform.GetChild(i);
				if (!((Object)(object)child == (Object)null) && !(Vector3.Distance(child.position, position) > 0.2f) && !((Object)(object)((Component)child).GetComponent<ModuleConnectObject>() != (Object)null))
				{
					string a = NormalizePrefabName(((Object)child).name ?? string.Empty);
					if (!string.IsNullOrEmpty(text) && string.Equals(a, text, StringComparison.OrdinalIgnoreCase))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static string NormalizePrefabName(string objectName)
		{
			if (string.IsNullOrEmpty(objectName))
			{
				return string.Empty;
			}
			string text = objectName.Trim();
			int num = text.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase);
			if (num >= 0)
			{
				text = text.Substring(0, num).TrimEnd();
			}
			return text;
		}

		private static void SanitizeSpawnedConnectObject(LevelGenerator generator, Vector3 position)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)generator == (Object)null) && !((Object)(object)generator.LevelParent == (Object)null))
			{
				ModuleConnectObject val = FindNearestConnectObject(generator.LevelParent.transform, position);
				if (!((Object)(object)val == (Object)null))
				{
					RemoveDoorObjectsFromConnectObject(((Component)val).gameObject);
				}
			}
		}

		private static ModuleConnectObject FindNearestConnectObject(Transform root, Vector3 position)
		{
			//IL_0060: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			ModuleConnectObject[] componentsInChildren = ((Component)root).GetComponentsInChildren<ModuleConnectObject>(true);
			if (componentsInChildren == null || componentsInChildren.Length == 0)
			{
				return null;
			}
			ModuleConnectObject result = null;
			float num = float.MaxValue;
			foreach (ModuleConnectObject val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					float num2 = Vector3.SqrMagnitude(((Component)val).transform.position - position);
					if (!(num2 > 0.04f) && num2 < num)
					{
						num = num2;
						result = val;
					}
				}
			}
			return result;
		}

		private static void RemoveDoorObjectsFromConnectObject(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			HashSet<int> hashSet = new HashSet<int>();
			Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				GameObject gameObject = ((Component)val).gameObject;
				if ((Object)(object)gameObject == (Object)null || (Object)(object)gameObject == (Object)(object)root || !IsLikelyDoorObject(gameObject))
				{
					continue;
				}
				GameObject connectDoorDestroyTarget = GetConnectDoorDestroyTarget(gameObject, root.transform);
				if (!((Object)(object)connectDoorDestroyTarget == (Object)null) && !((Object)(object)connectDoorDestroyTarget == (Object)(object)root))
				{
					int instanceID = ((Object)connectDoorDestroyTarget).GetInstanceID();
					if (!hashSet.Contains(instanceID))
					{
						hashSet.Add(instanceID);
						Object.Destroy((Object)(object)connectDoorDestroyTarget);
					}
				}
			}
		}

		private static GameObject GetConnectDoorDestroyTarget(GameObject candidate, Transform boundary)
		{
			if ((Object)(object)candidate == (Object)null)
			{
				return null;
			}
			Transform val = candidate.transform;
			while ((Object)(object)val.parent != (Object)null && (Object)(object)val.parent != (Object)(object)boundary)
			{
				GameObject gameObject = ((Component)val.parent).gameObject;
				if ((Object)(object)gameObject == (Object)null || (Object)(object)gameObject.GetComponent<ModuleConnectObject>() != (Object)null || !HasDirectDoorMarker(gameObject))
				{
					break;
				}
				val = val.parent;
			}
			return ((Object)(object)val != (Object)null) ? ((Component)val).gameObject : candidate;
		}

		private static void DisableOuterDoorObjects(GameObject root, Module module, Connection side)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			HashSet<int> hashSet = new HashSet<int>();
			Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				GameObject gameObject = ((Component)val).gameObject;
				if ((Object)(object)gameObject == (Object)null || !IsLikelyDoorObject(gameObject))
				{
					continue;
				}
				GameObject doorDestroyTarget = GetDoorDestroyTarget(gameObject, root.transform);
				if (!((Object)(object)doorDestroyTarget == (Object)null))
				{
					int instanceID = ((Object)doorDestroyTarget).GetInstanceID();
					if (!hashSet.Contains(instanceID))
					{
						hashSet.Add(instanceID);
						Object.Destroy((Object)(object)doorDestroyTarget);
					}
				}
			}
		}

		private static GameObject GetDoorDestroyTarget(GameObject candidate, Transform boundary)
		{
			if ((Object)(object)candidate == (Object)null)
			{
				return null;
			}
			Transform val = candidate.transform;
			while ((Object)(object)val.parent != (Object)null && (Object)(object)val.parent != (Object)(object)boundary)
			{
				GameObject gameObject = ((Component)val.parent).gameObject;
				if (!HasDirectDoorMarker(gameObject))
				{
					break;
				}
				val = val.parent;
			}
			return ((Object)(object)val != (Object)null) ? ((Component)val).gameObject : candidate;
		}

		private static bool HasDirectDoorMarker(GameObject gameObject)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return false;
			}
			if ((Object)(object)gameObject.GetComponent<PhysGrabHinge>() != (Object)null || (Object)(object)gameObject.GetComponent<DirtFinderMapDoor>() != (Object)null || (Object)(object)gameObject.GetComponent<DirtFinderMapDoorTarget>() != (Object)null)
			{
				return true;
			}
			if ((Object)(object)gameObject.GetComponent<PhysGrabObject>() != (Object)null || (Object)(object)gameObject.GetComponent<PhysGrabObjectImpactDetector>() != (Object)null)
			{
				return true;
			}
			if ((Object)(object)gameObject.GetComponent<HingeJoint>() != (Object)null || (Object)(object)gameObject.GetComponent<ConfigurableJoint>() != (Object)null || (Object)(object)gameObject.GetComponent<CharacterJoint>() != (Object)null || (Object)(object)gameObject.GetComponent<SpringJoint>() != (Object)null)
			{
				return true;
			}
			string text = (((Object)gameObject).name ?? string.Empty).ToLowerInvariant();
			string[] outerDoorKeywords = GetOuterDoorKeywords();
			foreach (string value in outerDoorKeywords)
			{
				if (!string.IsNullOrEmpty(value) && text.Contains(value))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsLikelyDoorObject(GameObject gameObject)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return false;
			}
			if ((Object)(object)gameObject.GetComponent<PhysGrabHinge>() != (Object)null || (Object)(object)gameObject.GetComponent<DirtFinderMapDoor>() != (Object)null || (Object)(object)gameObject.GetComponent<DirtFinderMapDoorTarget>() != (Object)null || (Object)(object)gameObject.GetComponent<PhysGrabObjectImpactDetector>() != (Object)null)
			{
				return true;
			}
			string text = (((Object)gameObject).name ?? string.Empty).ToLowerInvariant();
			string[] outerDoorKeywords = GetOuterDoorKeywords();
			bool flag = false;
			foreach (string value in outerDoorKeywords)
			{
				if (!string.IsNullOrEmpty(value) && text.Contains(value))
				{
					flag = true;
					break;
				}
			}
			bool flag2 = (Object)(object)gameObject.GetComponent<HingeJoint>() != (Object)null || (Object)(object)gameObject.GetComponent<ConfigurableJoint>() != (Object)null || (Object)(object)gameObject.GetComponent<CharacterJoint>() != (Object)null || (Object)(object)gameObject.GetComponent<SpringJoint>() != (Object)null;
			bool flag3 = (Object)(object)gameObject.GetComponent<Rigidbody>() != (Object)null;
			bool flag4 = (Object)(object)gameObject.GetComponent<Collider>() != (Object)null;
			bool flag5 = (Object)(object)gameObject.GetComponent<PhysGrabObject>() != (Object)null;
			if (flag2)
			{
				return true;
			}
			if (flag5 && flag)
			{
				return true;
			}
			if (flag && flag3)
			{
				return true;
			}
			if (flag && flag4)
			{
				return true;
			}
			return false;
		}

		private static string[] GetOuterDoorKeywords()
		{
			if (OuterDoorNameKeywords == null)
			{
				return new string[0];
			}
			string value = OuterDoorNameKeywords.Value;
			if (string.IsNullOrWhiteSpace(value))
			{
				return new string[0];
			}
			string[] array = value.Split(new char[5] { ',', ';', '\r', '\n', '\t' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = array[i].Trim().ToLowerInvariant();
			}
			return array;
		}

		private static Sprite ResolveLoadingGraphicSprite(Level level, int slot, Image currentImage)
		{
			Sprite levelLoadingGraphic = GetLevelLoadingGraphic(level, slot);
			if ((Object)(object)levelLoadingGraphic != (Object)null)
			{
				return levelLoadingGraphic;
			}
			if ((Object)(object)currentImage != (Object)null)
			{
				return currentImage.sprite;
			}
			return null;
		}

		private static Sprite GetLevelLoadingGraphic(Level level, int slot)
		{
			if ((Object)(object)level == (Object)null)
			{
				return null;
			}
			FieldInfo fieldInfo = null;
			switch (slot)
			{
			case 1:
				fieldInfo = LevelLoadingGraphic01Field;
				break;
			case 2:
				fieldInfo = LevelLoadingGraphic02Field;
				break;
			case 3:
				fieldInfo = LevelLoadingGraphic03Field;
				break;
			}
			if (fieldInfo == null)
			{
				return null;
			}
			try
			{
				object value = fieldInfo.GetValue(level);
				return (Sprite)((value is Sprite) ? value : null);
			}
			catch (Exception ex)
			{
				if (LogSource != null && DebugLog != null && DebugLog.Value)
				{
					LogSource.LogWarning((object)("GetLevelLoadingGraphic failed slot=" + slot + "`n" + ex));
				}
				return null;
			}
		}

		internal static bool IsTargetLoadingTexture(Sprite sprite)
		{
			if ((Object)(object)sprite == (Object)null)
			{
				return false;
			}
			string textureName = NormalizeTextureName(((Object)sprite).name);
			if (IsTargetLoadingTextureName(textureName))
			{
				return true;
			}
			if ((Object)(object)sprite.texture != (Object)null)
			{
				string textureName2 = NormalizeTextureName(((Object)sprite.texture).name);
				if (IsTargetLoadingTextureName(textureName2))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool IsTargetLoadingTextureName(string textureName)
		{
			if (string.IsNullOrWhiteSpace(textureName))
			{
				return false;
			}
			string b = NormalizeTextureName(textureName);
			for (int i = 0; i < TargetLoadingTextureNames.Length; i++)
			{
				string a = NormalizeTextureName(TargetLoadingTextureNames[i]);
				if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		internal static string NormalizeTextureName(string textureName)
		{
			if (string.IsNullOrWhiteSpace(textureName))
			{
				return string.Empty;
			}
			string text = textureName.Trim();
			if (text.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring(0, text.Length - 4);
			}
			return text.ToLowerInvariant();
		}

		private static void LogLoadingGraphicCandidateNames(LoadingUI loadingUI, Level level)
		{
			if (LogSource != null && !((Object)(object)level == (Object)null) && LogLoadingGraphicNames != null && LogLoadingGraphicNames.Value)
			{
				Image currentImage = (((Object)(object)loadingUI != (Object)null) ? loadingUI.loadingGraphic01 : null);
				Image currentImage2 = (((Object)(object)loadingUI != (Object)null) ? loadingUI.loadingGraphic02 : null);
				Image currentImage3 = (((Object)(object)loadingUI != (Object)null) ? loadingUI.loadingGraphic03 : null);
				LogSource.LogInfo((object)"[AllMapMerge][LoadingGraphicScan] Begin");
				LogLoadingGraphicSlotInfo("LoadingGraphic01", ResolveLoadingGraphicSprite(level, 1, currentImage), currentImage);
				LogLoadingGraphicSlotInfo("LoadingGraphic02", ResolveLoadingGraphicSprite(level, 2, currentImage2), currentImage2);
				LogLoadingGraphicSlotInfo("LoadingGraphic03", ResolveLoadingGraphicSprite(level, 3, currentImage3), currentImage3);
				LogSource.LogInfo((object)"[AllMapMerge][LoadingGraphicScan] End");
			}
		}

		private static void LogLoadingGraphicSlotInfo(string slotName, Sprite sourceSprite, Image currentImage)
		{
			string safeSpriteName = GetSafeSpriteName(sourceSprite);
			string safeTextureName = GetSafeTextureName(sourceSprite);
			string text = (((Object)(object)currentImage != (Object)null) ? GetSafeSpriteName(currentImage.sprite) : "null");
			string text2 = (((Object)(object)currentImage != (Object)null) ? GetSafeTextureName(