Decompiled source of DungeonGenerationPlus v1.2.0

DunGenPlus.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DunGen;
using DunGen.Adapters;
using DunGen.Graph;
using DunGenPlus.Attributes;
using DunGenPlus.Collections;
using DunGenPlus.Components;
using DunGenPlus.Components.DoorwayCleanupScripting;
using DunGenPlus.Components.Props;
using DunGenPlus.Components.Scrap;
using DunGenPlus.DevTools;
using DunGenPlus.DevTools.HoverUI;
using DunGenPlus.DevTools.Panels;
using DunGenPlus.DevTools.Panels.Collections;
using DunGenPlus.DevTools.UIElements;
using DunGenPlus.DevTools.UIElements.Collections;
using DunGenPlus.Generation;
using DunGenPlus.Managers;
using DunGenPlus.Patches;
using DunGenPlus.Utils;
using HarmonyLib;
using LethalLevelLoader;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
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: AssemblyTitle("DunGenPlus")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DunGenPlus")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("13cde60e-1975-463b-9da1-ccb3f3ebabd8")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
namespace DunGenPlus
{
	public class API
	{
		public static bool AddDunGenExtender(DungeonFlow dungeonFlow, DunGenExtender dunGenExtender)
		{
			if ((Object)(object)dungeonFlow == (Object)null)
			{
				Plugin.logger.LogError((object)"dungeonFlow was null");
				return false;
			}
			if (ContainsDungeonFlow(dungeonFlow))
			{
				Plugin.logger.LogWarning((object)("Already contains DunGenExtender asset for " + ((Object)dungeonFlow).name));
				return false;
			}
			Plugin.DunGenExtenders.Add(dungeonFlow, dunGenExtender);
			Plugin.logger.LogInfo((object)("Added DunGenExtender asset for " + ((Object)dungeonFlow).name));
			return true;
		}

		public static bool AddDunGenExtender(DunGenExtender dunGenExtender)
		{
			if ((Object)(object)dunGenExtender == (Object)null)
			{
				Plugin.logger.LogError((object)"dunGenExtender was null");
				return false;
			}
			return AddDunGenExtender(dunGenExtender.DungeonFlow, dunGenExtender);
		}

		public static bool ContainsDungeonFlow(DungeonFlow dungeonFlow)
		{
			return Plugin.DunGenExtenders.ContainsKey(dungeonFlow);
		}

		public static bool ContainsDungeonFlow(ExtendedDungeonFlow extendedDungeonFlow)
		{
			if ((Object)(object)extendedDungeonFlow == (Object)null)
			{
				return false;
			}
			return ContainsDungeonFlow(extendedDungeonFlow.DungeonFlow);
		}

		public static DunGenExtender GetDunGenExtender(DungeonFlow dungeonFlow)
		{
			if (Plugin.DunGenExtenders.TryGetValue(dungeonFlow, out var value))
			{
				return value;
			}
			return null;
		}

		public static DunGenExtender CreateDunGenExtender(DungeonFlow dungeonFlow)
		{
			DunGenExtender dunGenExtender = ScriptableObject.CreateInstance<DunGenExtender>();
			dunGenExtender.DungeonFlow = dungeonFlow;
			return dunGenExtender;
		}
	}
	internal class Assets
	{
		public static AssetBundle MainAssetBundle;

		public static GameObject DevDebugPrefab;

		public static void LoadAssets()
		{
			string[] files = Directory.GetFiles(Paths.PluginPath, "*.lethalbundle", SearchOption.AllDirectories);
			foreach (string fileName in files)
			{
				FileInfo fileInfo = new FileInfo(fileName);
				AssetBundleLoader.AddOnLethalBundleLoadedListener((Action<AssetBundle>)AutoAddLethalBundle, fileInfo.Name);
			}
		}

		private static void AutoAddLethalBundle(AssetBundle assetBundle)
		{
			if (!assetBundle.isStreamedSceneAssetBundle)
			{
				DunGenExtender[] array = assetBundle.LoadAllAssets<DunGenExtender>();
				ExtendedContent[] array2 = assetBundle.LoadAllAssets<ExtendedContent>();
				if (array2.Length == 0 && array.Length != 0)
				{
					Plugin.logger.LogWarning((object)".lethalbundle does not contain any ExtendedContent. Unless you are manually creating and adding your ExtendedDungeonFlow with code, the DunGenExtender will probably not work.");
				}
				DunGenExtender[] array3 = array;
				foreach (DunGenExtender dunGenExtender in array3)
				{
					API.AddDunGenExtender(dunGenExtender);
				}
			}
		}

		public static T Load<T>(string name, bool onlyReportErrors = true) where T : Object
		{
			if ((Object)(object)MainAssetBundle == (Object)null)
			{
				Plugin.logger.LogError((object)"Trying to load in asset but asset bundle is missing");
				return default(T);
			}
			T val = MainAssetBundle.LoadAsset<T>(name);
			bool flag = (Object)(object)val == (Object)null;
			if (flag || onlyReportErrors)
			{
				Plugin.logger.LogDebug((object)("Loading asset " + name));
			}
			if (flag)
			{
				Plugin.logger.LogError((object)"...but it was not found");
			}
			return val;
		}

		public static void LoadAssetBundle()
		{
			if ((Object)(object)MainAssetBundle == (Object)null)
			{
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				string[] manifestResourceNames = executingAssembly.GetManifestResourceNames();
				if (manifestResourceNames.Length >= 1)
				{
					string text = manifestResourceNames[0];
					using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text);
					Plugin.logger.LogDebug((object)("Loading resource " + text));
					MainAssetBundle = AssetBundle.LoadFromStream(stream);
				}
			}
			DevDebugPrefab = Assets.Load<GameObject>("DevDebug", onlyReportErrors: true);
		}
	}
	[Serializable]
	public class PropertyOverride<T>
	{
		[Tooltip("If false, use the value found in DungeonFlow. If true, use this Value instead.")]
		public bool Override;

		public T Value;

		public PropertyOverride(bool _override, T value)
		{
			Override = _override;
			Value = value;
		}
	}
	[CreateAssetMenu(fileName = "Main Path Extender", menuName = "DunGenExtender/Main Path Extender", order = 2)]
	public class MainPathExtender : ScriptableObject
	{
		public PropertyOverride<IntRange> Length = new PropertyOverride<IntRange>(_override: false, new IntRange(5, 10));

		public PropertyOverride<BranchMode> BranchMode = new PropertyOverride<BranchMode>(_override: false, (BranchMode)0);

		public PropertyOverride<IntRange> BranchCount = new PropertyOverride<IntRange>(_override: false, new IntRange(1, 5));

		public PropertyOverride<List<GraphNode>> Nodes = new PropertyOverride<List<GraphNode>>(_override: false, new List<GraphNode>());

		public PropertyOverride<List<GraphLine>> Lines = new PropertyOverride<List<GraphLine>>(_override: false, new List<GraphLine>());

		[Header("DEV ONLY: DON'T TOUCH")]
		[ReadOnly]
		public string Version = "0";

		public static IntRange GetLength(MainPathExtender extender, DungeonFlow flow)
		{
			if (Object.op_Implicit((Object)(object)extender) && extender.Length.Override)
			{
				return extender.Length.Value;
			}
			return flow.Length;
		}

		public static BranchMode GetBranchMode(MainPathExtender extender, DungeonFlow flow)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)extender) && extender.BranchMode.Override)
			{
				return extender.BranchMode.Value;
			}
			return flow.BranchMode;
		}

		public static IntRange GetBranchCount(MainPathExtender extender, DungeonFlow flow)
		{
			if (Object.op_Implicit((Object)(object)extender) && extender.BranchCount.Override)
			{
				return extender.BranchCount.Value;
			}
			return flow.BranchCount;
		}

		public static List<GraphNode> GetNodes(MainPathExtender extender, DungeonFlow flow)
		{
			if (Object.op_Implicit((Object)(object)extender) && extender.Nodes.Override)
			{
				return extender.Nodes.Value;
			}
			return flow.Nodes;
		}

		public static List<GraphLine> GetLines(MainPathExtender extender, DungeonFlow flow)
		{
			if (Object.op_Implicit((Object)(object)extender) && extender.Lines.Override)
			{
				return extender.Lines.Value;
			}
			return flow.Lines;
		}
	}
	internal class PluginConfig
	{
		public static ConfigEntry<bool> EnableDevDebugTools;

		public static void SetupConfig(ConfigFile cfg)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0027: Expected O, but got Unknown
			EnableDevDebugTools = cfg.Bind<bool>(new ConfigDefinition("Dev", "Enable Dev Debug Tools"), false, new ConfigDescription("If enabled, allows the dev debug tools to be usable in the ship.\n\nPress LeftAlt + M to activate.", (AcceptableValueBase)null, Array.Empty<object>()));
		}
	}
	[CreateAssetMenu(fileName = "DunGen Extender", menuName = "DunGenExtender/DunGen Extender", order = 1)]
	public class DunGenExtender : ScriptableObject
	{
		[Tooltip("DunGenExtender will only influence this DungeonFlow")]
		public DungeonFlow DungeonFlow;

		public DunGenExtenderProperties Properties = new DunGenExtenderProperties();

		public DunGenExtenderEvents Events = new DunGenExtenderEvents();

		[Header("DEV ONLY: DON'T TOUCH")]
		[ReadOnly]
		public string Version = CURRENT_VERSION;

		internal bool Active = true;

		public static readonly string CURRENT_VERSION = "1";

		public void OnValidate()
		{
			if (Version == "0")
			{
				Properties.AdditionalTilesProperties.CopyFrom(Properties.ForcedTilesProperties);
				Version = "1";
			}
		}
	}
	[BepInPlugin("dev.ladyalice.dungenplus", "Dungeon Generation Plus", "1.2.0")]
	[BepInDependency("imabatby.lethallevelloader", "1.2.0.3")]
	[BepInProcess("Lethal Company.exe")]
	public class Plugin : BaseUnityPlugin
	{
		internal const string modGUID = "dev.ladyalice.dungenplus";

		private const string modName = "Dungeon Generation Plus";

		private const string modVersion = "1.2.0";

		internal readonly Harmony Harmony = new Harmony("dev.ladyalice.dungenplus");

		internal static Dictionary<DungeonFlow, DunGenExtender> DunGenExtenders = new Dictionary<DungeonFlow, DunGenExtender>();

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource logger { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			logger = Logger.CreateLogSource("dev.ladyalice.dungenplus");
			logger.LogInfo((object)"Plugin Dungeon Generation Plus has been added!");
			PluginConfig.SetupConfig(((BaseUnityPlugin)this).Config);
			Harmony.PatchAll(typeof(DungeonGeneratorPatch));
			Harmony.PatchAll(typeof(DoorwayConnectionPatch));
			Harmony.PatchAll(typeof(RoundManagerPatch));
			try
			{
				Harmony.PatchAll(typeof(LethalLevelLoaderPatches));
			}
			catch (Exception ex)
			{
				logger.LogError((object)"Failed to patch LLL for dev debug. You can ignore this.");
				logger.LogError((object)ex);
			}
			Assets.LoadAssets();
			Assets.LoadAssetBundle();
			DungeonManager.GlobalDungeonEvents.onBeforeDungeonGenerate.AddListener((ParameterEvent<RoundManager>)OnDunGenExtenderLoad);
			DoorwayManager.onMainEntranceTeleportSpawnedEvent.AddEvent("DoorwayCleanup", DoorwayManager.onMainEntranceTeleportSpawnedFunction);
		}

		private void OnDunGenExtenderLoad(RoundManager roundManager)
		{
			DunGenPlusGenerator.Deactivate();
			DungeonGenerator generator = roundManager.dungeonGenerator.Generator;
			DungeonFlow dungeonFlow = generator.DungeonFlow;
			DunGenExtender dunGenExtender = API.GetDunGenExtender(dungeonFlow);
			if (Object.op_Implicit((Object)(object)dunGenExtender) && dunGenExtender.Active)
			{
				logger.LogInfo((object)("Loading DunGenExtender for " + ((Object)dungeonFlow).name));
				DunGenPlusGenerator.Activate(generator, dunGenExtender);
			}
			else
			{
				logger.LogInfo((object)"Did not load a DunGenExtenderer");
				DunGenPlusGenerator.Deactivate();
			}
		}
	}
}
namespace DunGenPlus.Utils
{
	internal class InjectionDictionary
	{
		public string name;

		public List<CodeInstruction> instructions;

		public CodeInstruction[] injections;

		private int counter;

		public InjectionDictionary(string name, MethodInfo methodInjection, params CodeInstruction[] instructions)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			this.name = name;
			injections = (CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Call, (object)methodInjection)
			};
			this.instructions = instructions.ToList();
		}

		public InjectionDictionary(string name, CodeInstruction[] codeInjections, params CodeInstruction[] instructions)
		{
			this.name = name;
			injections = codeInjections;
			this.instructions = instructions.ToList();
		}

		public void ResetCounter()
		{
			counter = 0;
		}

		public void AddCounter()
		{
			counter++;
		}

		public void Report(string debugFunction, int? expectedCounter)
		{
			if (counter == 0)
			{
				Plugin.logger.LogError((object)(debugFunction + " could not inject " + name + ". Probably scary"));
			}
			else if (!expectedCounter.HasValue)
			{
				Plugin.logger.LogDebug((object)$"{debugFunction} inject {name} {counter} time(s)");
			}
			else if (expectedCounter.Value != counter)
			{
				Plugin.logger.LogWarning((object)$"{debugFunction} inject {name} {counter} time(s) (Expected {expectedCounter.Value}). Probably not an error but be warned");
			}
		}
	}
	internal abstract class InstructionSequence
	{
		protected enum AdvanceResult
		{
			Failed,
			Advanced,
			Finished
		}

		protected List<Func<CodeInstruction, bool>> seq;

		protected string name;

		protected string extraErrorMessage;

		protected int stage;

		protected bool completed;

		protected bool single;

		public InstructionSequence(string name, bool single = true, string extraErrorMessage = null)
		{
			seq = new List<Func<CodeInstruction, bool>>();
			stage = 0;
			completed = false;
			this.name = name;
			this.single = single;
			this.extraErrorMessage = extraErrorMessage;
		}

		public void Add(Func<CodeInstruction, bool> next)
		{
			seq.Add(next);
		}

		public void AddBasic(OpCode opcode)
		{
			seq.Add((CodeInstruction i) => i.opcode == opcode);
		}

		public void AddBasic(OpCode opcode, object operand)
		{
			seq.Add((CodeInstruction i) => i.opcode == opcode && i.operand == operand);
		}

		public void AddBasicLocal(OpCode opcode, int operand)
		{
			seq.Add((CodeInstruction i) => i.opcode == opcode && (i.operand as LocalBuilder).LocalIndex == operand);
		}

		public void AddAny()
		{
			seq.Add(null);
		}

		public void AddOperandTypeCheck(OpCode opcode, Type operandType)
		{
			seq.Add(delegate(CodeInstruction i)
			{
				FieldInfo fieldInfo = i.operand as FieldInfo;
				return i.opcode == opcode && fieldInfo != null && fieldInfo.FieldType == operandType;
			});
		}

		public void AddBasicWithAlternateMethodName(OpCode opcode, object operand, string methodName)
		{
			seq.Add(delegate(CodeInstruction i)
			{
				if (i.opcode == opcode && i.operand == operand)
				{
					return true;
				}
				MethodInfo methodInfo = i.operand as MethodInfo;
				return (methodInfo != null && methodInfo.Name == methodName) ? true : false;
			});
		}

		public void AddSpecial(OpCode opcode, Func<CodeInstruction, bool> extra)
		{
			seq.Add((CodeInstruction i) => i.opcode == opcode && extra(i));
		}

		public void ReportComplete()
		{
			if (!completed)
			{
				string text = (string.IsNullOrWhiteSpace(extraErrorMessage) ? "BIG PROBLEM!" : extraErrorMessage);
				Plugin.logger.LogError((object)("HarmonyTranspiler for " + name + " has failed. " + text));
			}
		}

		protected AdvanceResult AdvanceStage(CodeInstruction current)
		{
			Func<CodeInstruction, bool> func = seq[stage];
			AdvanceResult advanceResult = AdvanceResult.Failed;
			if (func == null)
			{
				func = seq[stage + 1];
				if (func(current))
				{
					stage += 2;
				}
				advanceResult = AdvanceResult.Advanced;
			}
			else if (func(current))
			{
				stage++;
				advanceResult = AdvanceResult.Advanced;
			}
			else
			{
				stage = 0;
				advanceResult = AdvanceResult.Failed;
			}
			if (stage >= seq.Count)
			{
				if (completed && single)
				{
					throw new Exception("Found multiple valid " + name + " instructions");
				}
				stage = 0;
				completed = true;
				advanceResult = AdvanceResult.Finished;
			}
			return advanceResult;
		}
	}
	internal class InstructionSequenceStandard : InstructionSequence
	{
		public InstructionSequenceStandard(string name, bool single = true, string extraErrorMessage = null)
			: base(name, single, extraErrorMessage)
		{
		}

		public bool VerifyStage(CodeInstruction current)
		{
			return AdvanceStage(current) == AdvanceResult.Finished;
		}
	}
	internal class InstructionSequenceHold : InstructionSequence
	{
		public enum HoldResult
		{
			None,
			Hold,
			Release,
			Finished
		}

		public List<CodeInstruction> Instructions;

		private new List<Func<CodeInstruction, bool>> seq;

		private new string name;

		private new string extraErrorMessage;

		private new int stage = 0;

		private new bool completed = false;

		public InstructionSequenceHold(string name, bool single = true, string extraErrorMessage = null)
			: base(name, single, extraErrorMessage)
		{
			Instructions = new List<CodeInstruction>();
		}

		public HoldResult VerifyStage(CodeInstruction current)
		{
			switch (AdvanceStage(current))
			{
			case AdvanceResult.Failed:
				if (Instructions.Count > 0)
				{
					Instructions.Add(current);
					return HoldResult.Release;
				}
				return HoldResult.None;
			case AdvanceResult.Advanced:
				Instructions.Add(current);
				return HoldResult.Hold;
			default:
				Instructions.Add(current);
				return HoldResult.Finished;
			}
		}

		public void ClearInstructions()
		{
			Instructions.Clear();
		}
	}
	internal class TranspilerUtilities
	{
		public static IEnumerable<CodeInstruction> InjectMethod(IEnumerable<CodeInstruction> instructions, InjectionDictionary injection, string debugFunction, int? expectedCounter = null)
		{
			List<CodeInstruction> targets = injection.instructions;
			CodeInstruction[] codeInjections = injection.injections;
			injection.ResetCounter();
			foreach (CodeInstruction i in instructions)
			{
				foreach (CodeInstruction t in targets)
				{
					if (!(i.opcode == t.opcode) || i.operand != t.operand)
					{
						continue;
					}
					yield return i;
					CodeInstruction[] array = codeInjections;
					for (int j = 0; j < array.Length; j++)
					{
						yield return array[j];
					}
					injection.AddCounter();
					goto IL_0215;
				}
				yield return i;
				IL_0215:;
			}
			injection.Report(debugFunction, expectedCounter);
		}

		public static bool IsInstructionNearFloatValue(CodeInstruction instruction, float value)
		{
			return Mathf.Abs((float)instruction.operand - value) < 0.1f;
		}

		public static void PrintInstructions(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				string text = instruction.opcode.ToString();
				string text2 = ((instruction.operand != null) ? instruction.operand.ToString() : "NULL");
				Plugin.logger.LogInfo((object)(text + ": " + text2));
			}
		}
	}
	public class ActionList
	{
		public string name;

		public List<(string name, Action action)> actionList;

		public List<(string name, Action action)> temporaryActionList;

		public ActionList(string name)
		{
			this.name = name;
			actionList = new List<(string, Action)>();
			temporaryActionList = new List<(string, Action)>();
		}

		public void AddEvent(string name, Action act)
		{
			actionList.Add((name, act));
		}

		public void AddTemporaryEvent(string name, Action act)
		{
			temporaryActionList.Add((name, act));
		}

		public void Call()
		{
			foreach (var action in actionList)
			{
				try
				{
					action.action();
				}
				catch (Exception ex)
				{
					Plugin.logger.LogError((object)("Error with event " + name + "/" + action.name));
					Plugin.logger.LogError((object)ex.ToString());
				}
			}
			foreach (var temporaryAction in temporaryActionList)
			{
				try
				{
					temporaryAction.action();
				}
				catch (Exception ex2)
				{
					Plugin.logger.LogError((object)("Error with event " + name + "/" + temporaryAction.name));
					Plugin.logger.LogError((object)ex2.ToString());
				}
			}
			ClearTemporaryActionList();
		}

		public void ClearTemporaryActionList()
		{
			temporaryActionList.Clear();
		}
	}
}
namespace DunGenPlus.Patches
{
	internal class DoorwayConnectionPatch
	{
		[HarmonyPatch(typeof(DungeonProxy), "ConnectOverlappingDoorways")]
		[HarmonyPrefix]
		public static void ConnectOverlappingDoorwaysPrePatch(ref DungeonProxy __instance)
		{
			IEnumerable<DoorwayProxy> list = __instance.AllTiles.SelectMany((TileProxy t) => t.Doorways);
			DoorwaySistersRule.UpdateCache(list);
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(DungeonProxy), "ConnectOverlappingDoorways")]
		public static IEnumerable<CodeInstruction> ConnectOverlappingDoorwaysPatch(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo callFunction = typeof(DungeonFlow).GetMethod("CanDoorwaysConnect", BindingFlags.Instance | BindingFlags.Public);
			InstructionSequenceStandard sequence = new InstructionSequenceStandard("doorway connect", single: false);
			sequence.AddBasic(OpCodes.Callvirt, callFunction);
			sequence.AddBasic(OpCodes.Brfalse);
			foreach (CodeInstruction instruction in instructions)
			{
				if (sequence.VerifyStage(instruction))
				{
					MethodInfo method = typeof(DoorwaySistersRule).GetMethod("CanDoorwaysConnect", BindingFlags.Static | BindingFlags.Public);
					MethodInfo getTileProxy = typeof(DoorwayProxy).GetMethod("get_TileProxy", BindingFlags.Instance | BindingFlags.Public);
					yield return new CodeInstruction(OpCodes.Ldloc_2, (object)null);
					yield return new CodeInstruction(OpCodes.Callvirt, (object)getTileProxy);
					yield return new CodeInstruction(OpCodes.Ldloc_S, (object)4);
					yield return new CodeInstruction(OpCodes.Callvirt, (object)getTileProxy);
					yield return new CodeInstruction(OpCodes.Ldloc_2, (object)null);
					yield return new CodeInstruction(OpCodes.Ldloc_S, (object)4);
					yield return new CodeInstruction(OpCodes.Call, (object)method);
					yield return instruction;
				}
				else
				{
					yield return instruction;
				}
			}
			sequence.ReportComplete();
		}
	}
	internal class DungeonGeneratorPatch
	{
		public static TilePlacementResult lastTilePlacementResult;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(DungeonGenerator), "InnerGenerate")]
		public static void InnerGeneratePatch(ref DungeonGenerator __instance, bool isRetry, ref IEnumerator __result)
		{
			if (DevDebugManager.IsActive && !isRetry)
			{
				DevDebugManager.Instance.RecordNewSeed(__instance.ChosenSeed);
			}
			if (DunGenPlusGenerator.Active && DunGenPlusGenerator.ActiveAlternative)
			{
				DunGenPlusGenerator.SetCurrentMainPathExtender(0);
				MainRoomDoorwayGroups.ModifyGroupBasedOnBehaviourSimpleOnce = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(DungeonGenerator), "GenerateMainPath")]
		public static void GenerateMainPathPatch(ref DungeonGenerator __instance, ref IEnumerator __result)
		{
			if (DunGenPlusGenerator.Active && DunGenPlusGenerator.ActiveAlternative)
			{
				DunGenPlusGenerator.RandomizeLineArchetypes(__instance, randomizeMainPath: true);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(DungeonGenerator), "GenerateBranchPaths")]
		public static void GenerateBranchPathsPatch(ref DungeonGenerator __instance, ref IEnumerator __result)
		{
			if (DunGenPlusGenerator.Active && DunGenPlusGenerator.ActiveAlternative)
			{
				__result = DunGenPlusGenerator.GenerateAlternativeMainPaths(__instance);
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		public static IEnumerable<CodeInstruction> GenerateMainPathPatch(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo addArchFunction = typeof(List<DungeonArchetype>).GetMethod("Add", BindingFlags.Instance | BindingFlags.Public);
			InstructionSequenceStandard archSequence = new InstructionSequenceStandard("archetype node");
			archSequence.AddOperandTypeCheck(OpCodes.Ldfld, typeof(List<DungeonArchetype>));
			archSequence.AddBasic(OpCodes.Ldnull);
			archSequence.AddBasic(OpCodes.Callvirt, addArchFunction);
			InstructionSequenceStandard attachToSequence = new InstructionSequenceStandard("attach to");
			attachToSequence.AddBasicLocal(OpCodes.Stloc_S, 13);
			foreach (CodeInstruction instruction in instructions)
			{
				if (archSequence.VerifyStage(instruction))
				{
					MethodInfo randomStreamMethod = typeof(DungeonGenerator).GetMethod("get_RandomStream", BindingFlags.Instance | BindingFlags.Public);
					MethodInfo modifyMethod2 = typeof(DunGenPlusGenerator).GetMethod("ModifyMainBranchNodeArchetype", BindingFlags.Static | BindingFlags.Public);
					yield return new CodeInstruction(OpCodes.Ldloc_S, (object)8);
					yield return new CodeInstruction(OpCodes.Ldloc_1, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)randomStreamMethod);
					yield return new CodeInstruction(OpCodes.Call, (object)modifyMethod2);
					yield return instruction;
				}
				else if (attachToSequence.VerifyStage(instruction))
				{
					yield return instruction;
					MethodInfo modifyMethod = typeof(MainRoomDoorwayGroups).GetMethod("ModifyGroupBasedOnBehaviourSimple", BindingFlags.Static | BindingFlags.Public);
					yield return new CodeInstruction(OpCodes.Ldloc_S, (object)13);
					yield return new CodeInstruction(OpCodes.Call, (object)modifyMethod);
				}
				else
				{
					yield return instruction;
				}
			}
			archSequence.ReportComplete();
			attachToSequence.ReportComplete();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		public static IEnumerable<CodeInstruction> GenerateMainPathGetLineAtDepthPatch(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo getLineFunction = typeof(DungeonFlow).GetMethod("GetLineAtDepth", BindingFlags.Instance | BindingFlags.Public);
			FieldInfo nodesField = typeof(DungeonFlow).GetField("Nodes", BindingFlags.Instance | BindingFlags.Public);
			InstructionSequenceStandard lineSequence = new InstructionSequenceStandard("GetLineAtDepth");
			lineSequence.AddBasic(OpCodes.Callvirt, getLineFunction);
			InstructionSequenceStandard nodesSequence = new InstructionSequenceStandard("Nodes", single: false);
			nodesSequence.AddBasic(OpCodes.Ldfld, nodesField);
			foreach (CodeInstruction instruction in instructions)
			{
				if (lineSequence.VerifyStage(instruction))
				{
					MethodInfo specialFunction2 = typeof(DunGenPlusGenerator).GetMethod("GetLineAtDepth", BindingFlags.Static | BindingFlags.Public);
					yield return new CodeInstruction(OpCodes.Call, (object)specialFunction2);
				}
				else if (nodesSequence.VerifyStage(instruction))
				{
					MethodInfo specialFunction = typeof(DunGenPlusGenerator).GetMethod("GetNodes", BindingFlags.Static | BindingFlags.Public);
					yield return new CodeInstruction(OpCodes.Call, (object)specialFunction);
				}
				else
				{
					yield return instruction;
				}
			}
			lineSequence.ReportComplete();
			nodesSequence.ReportComplete();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(BranchCountHelper), "ComputeBranchCounts")]
		public static IEnumerable<CodeInstruction> ComputeBranchCountsPatch(IEnumerable<CodeInstruction> instructions)
		{
			FieldInfo branchModeField = typeof(DungeonFlow).GetField("BranchMode", BindingFlags.Instance | BindingFlags.Public);
			InstructionSequenceStandard branchSequence = new InstructionSequenceStandard("BranchMode", single: false);
			branchSequence.AddBasic(OpCodes.Ldfld, branchModeField);
			foreach (CodeInstruction instruction in instructions)
			{
				if (branchSequence.VerifyStage(instruction))
				{
					MethodInfo specialFunction = typeof(DunGenPlusGenerator).GetMethod("GetBranchMode", BindingFlags.Static | BindingFlags.Public);
					yield return new CodeInstruction(OpCodes.Call, (object)specialFunction);
				}
				else
				{
					yield return instruction;
				}
			}
			branchSequence.ReportComplete();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(BranchCountHelper), "ComputeBranchCountsGlobal")]
		public static IEnumerable<CodeInstruction> ComputeBranchCountsGlobalPatch(IEnumerable<CodeInstruction> instructions)
		{
			FieldInfo branchCountField = typeof(DungeonFlow).GetField("BranchCount", BindingFlags.Instance | BindingFlags.Public);
			InstructionSequenceStandard branchSequence = new InstructionSequenceStandard("BranchCount");
			branchSequence.AddBasic(OpCodes.Ldfld, branchCountField);
			foreach (CodeInstruction instruction in instructions)
			{
				if (branchSequence.VerifyStage(instruction))
				{
					MethodInfo specialFunction = typeof(DunGenPlusGenerator).GetMethod("GetBranchCount", BindingFlags.Static | BindingFlags.Public);
					yield return new CodeInstruction(OpCodes.Call, (object)specialFunction);
				}
				else
				{
					yield return instruction;
				}
			}
			branchSequence.ReportComplete();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		public static IEnumerable<CodeInstruction> InnerGenerateLengthPatch(IEnumerable<CodeInstruction> instructions)
		{
			FieldInfo lengthField = typeof(DungeonFlow).GetField("Length", BindingFlags.Instance | BindingFlags.Public);
			MethodInfo getIsEditor = typeof(Application).GetMethod("get_isEditor", BindingFlags.Static | BindingFlags.Public);
			InstructionSequenceStandard lengthSequence = new InstructionSequenceStandard("Length");
			lengthSequence.AddBasic(OpCodes.Ldfld, lengthField);
			InstructionSequenceStandard editorCheck = new InstructionSequenceStandard("Editor");
			editorCheck.AddBasic(OpCodes.Call, getIsEditor);
			foreach (CodeInstruction instruction in instructions)
			{
				if (lengthSequence.VerifyStage(instruction))
				{
					MethodInfo specialFunction2 = typeof(DunGenPlusGenerator).GetMethod("GetLength", BindingFlags.Static | BindingFlags.Public);
					yield return new CodeInstruction(OpCodes.Call, (object)specialFunction2);
				}
				else if (editorCheck.VerifyStage(instruction))
				{
					MethodInfo specialFunction = typeof(DunGenPlusGenerator).GetMethod("AllowRetryStop", BindingFlags.Static | BindingFlags.Public);
					yield return instruction;
					yield return new CodeInstruction(OpCodes.Call, (object)specialFunction);
				}
				else
				{
					yield return instruction;
				}
			}
			lengthSequence.ReportComplete();
			editorCheck.ReportComplete();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(RoundManager), "FinishGeneratingLevel")]
		public static void GenerateBranchPathsPatch()
		{
			if (DunGenPlusGenerator.Active)
			{
				Plugin.logger.LogDebug((object)"Alt. InnerGenerate() function complete");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(RoundManager), "SetPowerOffAtStart")]
		public static void SetPowerOffAtStartPatch()
		{
			DoorwayManager.onMainEntranceTeleportSpawnedEvent.Call();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(DungeonGenerator), "PostProcess")]
		public static void GenerateBranchPathsPatch(ref DungeonGenerator __instance)
		{
			if (DunGenPlusGenerator.Active)
			{
				int value = __instance.RandomStream.Next(999);
				SpawnSyncedObjectCycle.UpdateCycle(value);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(DungeonGenerator), "AddTilePlacementResult")]
		public static void AddTilePlacementResultPatch(TilePlacementResult result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			lastTilePlacementResult = result;
		}
	}
	internal class LethalLevelLoaderPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(Patches), "DungeonGeneratorGenerate_Prefix")]
		public static bool DungeonGeneratorGenerate_Prefix_Prefix()
		{
			return (Object)(object)DevDebugManager.Instance == (Object)null;
		}
	}
	public class RoundManagerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(RoundManager), "Awake")]
		public static void AwakePatch()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			if (PluginConfig.EnableDevDebugTools.Value)
			{
				GameObject val = new GameObject("DevDebugOpen", new Type[1] { typeof(DevDebugOpen) });
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(RoundManager), "waitForScrapToSpawnToSync")]
		public static void waitForScrapToSpawnToSyncPatch(ref RoundManager __instance, ref NetworkObjectReference[] spawnedScrap, ref int[] scrapValues)
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			if (!DunGenPlusGenerator.Active || !DunGenPlusGenerator.Properties.MiscellaneousProperties.UseRandomGuaranteedScrapSpawn)
			{
				return;
			}
			List<NetworkObjectReference> list = spawnedScrap.ToList();
			List<int> list2 = scrapValues.ToList();
			RandomGuaranteedScrapSpawn[] array = Object.FindObjectsOfType<RandomGuaranteedScrapSpawn>();
			RandomGuaranteedScrapSpawn.ResetCache();
			RandomGuaranteedScrapSpawn[] array2 = array;
			foreach (RandomGuaranteedScrapSpawn randomGuaranteedScrapSpawn in array2)
			{
				(NetworkObject, int) tuple = randomGuaranteedScrapSpawn.CreateItem(__instance, __instance.currentLevel.spawnableScrap);
				if ((Object)(object)tuple.Item1 != (Object)null)
				{
					Plugin.logger.LogDebug((object)$"Created guaranteed item {((Object)((Component)tuple.Item1).gameObject).name} w/ value {tuple.Item2}");
					list.Add(NetworkObjectReference.op_Implicit(tuple.Item1));
					list2.Add(tuple.Item2);
				}
			}
			spawnedScrap = list.ToArray();
			scrapValues = list2.ToArray();
		}
	}
	internal class StartOfRoundPatch
	{
		public static readonly string[] validDungeonFlowTargets = new string[4] { "Level1Flow", "Level2Flow", "Level1FlowExtraLarge", "Level1Flow3Exits" };

		public static readonly Dictionary<string, int> validStartTileTargets = new Dictionary<string, int>
		{
			{ "StartRoom", 2 },
			{ "ManorStartRoom", 3 }
		};

		[HarmonyPatch(typeof(RoundManager), "Awake")]
		[HarmonyPrefix]
		public static void AwakePatch(ref RoundManager __instance)
		{
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Expected O, but got Unknown
			IEnumerable<DungeonFlow> enumerable = __instance.dungeonFlowTypes.Select((IndoorMapType d) => d.dungeonFlow);
			foreach (DungeonFlow item in enumerable)
			{
				if (!validDungeonFlowTargets.Contains(((Object)item).name) || API.ContainsDungeonFlow(item))
				{
					continue;
				}
				Plugin.logger.LogInfo((object)("Creating DunGenExtender for " + ((Object)item).name));
				IEnumerable<GameObject> enumerable2 = from i in (from i in (from i in item.Lines.Select((GraphLine i) => i.DungeonArchetypes).SelectMany((List<DungeonArchetype> i) => i)
							select i.TileSets).SelectMany((List<TileSet> i) => i)
						select i.TileWeights.Weights).SelectMany((List<GameObjectChance> i) => i)
					select i.Value;
				foreach (GameObject item2 in enumerable2)
				{
					if (validStartTileTargets.TryGetValue(((Object)item2).name, out var value))
					{
						DunGenExtender dunGenExtender = API.CreateDunGenExtender(item);
						DunGenExtenderProperties properties = dunGenExtender.Properties;
						properties.MainPathProperties.MainPathCount = value;
						properties.MainPathProperties.MainRoomTilePrefab = item2;
						item.Length = new IntRange(item.Length.Min / 2, item.Length.Max / 2);
						Plugin.logger.LogInfo((object)$"New length: {item.Length}");
						if (((Object)item2).name == "StartRoom")
						{
							List<GraphLine> lines = item.Lines;
							lines[0].Length = 0.2f;
							GraphLine obj = lines[1];
							obj.Length -= 0.2f - lines[1].Position;
							lines[1].Position = 0.2f;
						}
						API.AddDunGenExtender(dunGenExtender);
						break;
					}
				}
			}
		}
	}
}
namespace DunGenPlus.Managers
{
	public static class DoorwayManager
	{
		public static ActionList onMainEntranceTeleportSpawnedEvent = new ActionList("onMainEntranceTeleportSpawned");

		public static List<DoorwayCleanup> doorwayCleanupList;

		public static void ResetList()
		{
			doorwayCleanupList = new List<DoorwayCleanup>();
		}

		public static void AddDoorwayCleanup(DoorwayCleanup cleanup)
		{
			doorwayCleanupList.Add(cleanup);
		}

		public static void onMainEntranceTeleportSpawnedFunction()
		{
			if (!DunGenPlusGenerator.Active)
			{
				return;
			}
			foreach (DoorwayCleanup doorwayCleanup in doorwayCleanupList)
			{
				doorwayCleanup.SetBlockers(state: false);
				doorwayCleanup.Cleanup();
			}
			try
			{
				RuntimeDungeon dungeonGenerator = RoundManager.Instance.dungeonGenerator;
				UnityNavMeshAdapter componentInChildren = ((Component)((Component)dungeonGenerator).transform.parent).GetComponentInChildren<UnityNavMeshAdapter>();
				((BaseAdapter)componentInChildren).Run(dungeonGenerator.Generator);
				Plugin.logger.LogDebug((object)"Rebuild nav mesh");
			}
			catch (Exception ex)
			{
				Plugin.logger.LogError((object)"Failed to rebuild nav mesh");
				Plugin.logger.LogError((object)ex.ToString());
			}
		}
	}
}
namespace DunGenPlus.Generation
{
	internal class DunGenPlusGenerator
	{
		private class BranchPathProxy
		{
			public TileProxy mainPathTile;

			public int mainPathIndex;

			public List<TilePlacementResultProxy> list;

			public float weight;

			public Dictionary<TileProxy, InjectedTile> injectedTiles;

			public List<InjectedTile> tilesPendingInjection;

			public BranchPathProxy(DungeonGenerator gen, TileProxy attachTileProxy)
			{
				mainPathTile = attachTileProxy;
				mainPathIndex = GetMainPathIndexFromTileProxy(attachTileProxy);
				list = new List<TilePlacementResultProxy>();
				weight = 0f;
				injectedTiles = new Dictionary<TileProxy, InjectedTile>(gen.injectedTiles);
				tilesPendingInjection = new List<InjectedTile>(gen.tilesPendingInjection);
			}

			public void CalculateWeight(DungeonGenerator gen)
			{
				//IL_0177: Unknown result type (might be due to invalid IL or missing references)
				//IL_017e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0183: Unknown result type (might be due to invalid IL or missing references)
				int count = list.Count;
				if (count == 0)
				{
					return;
				}
				TilePlacementResultProxy tilePlacementResultProxy = list[count - 1];
				BranchPathMultiSimulationProperties branchPathMultiSimulationProperties = Properties.BranchPathMultiSimulationProperties;
				int branchDepth = tilePlacementResultProxy.tileProxy.Placement.BranchDepth;
				float normalizedBranchDepth = tilePlacementResultProxy.tileProxy.Placement.NormalizedBranchDepth;
				weight += branchPathMultiSimulationProperties.GetWeightBase(branchDepth, normalizedBranchDepth);
				IEnumerable<DoorwayProxy> enumerable = gen.proxyDungeon.AllTiles.SelectMany((TileProxy t) => t.Doorways);
				foreach (TilePlacementResultProxy item in list)
				{
					foreach (DoorwayProxy item2 in enumerable)
					{
						if (item2.TileProxy == mainPathTile)
						{
							continue;
						}
						int mainPathIndexFromTileProxy = GetMainPathIndexFromTileProxy(item2.TileProxy);
						foreach (DoorwayProxy doorway in item.tileProxy.doorways)
						{
							if (item2.TileProxy != item.previousDoorway.TileProxy && gen.DungeonFlow.CanDoorwaysConnect(item2.TileProxy.PrefabTile, doorway.TileProxy.PrefabTile, item2.DoorwayComponent, doorway.DoorwayComponent) && (double)Vector3.SqrMagnitude(item2.Position - doorway.Position) < 1E-05)
							{
								int num = Mathf.Abs(item2.TileProxy.Placement.PathDepth - doorway.TileProxy.Placement.PathDepth);
								float normalizedDepthDifference = Mathf.Abs(item2.TileProxy.Placement.NormalizedPathDepth - doorway.TileProxy.Placement.NormalizedPathDepth);
								bool samePath = mainPathIndex == mainPathIndexFromTileProxy;
								weight += branchPathMultiSimulationProperties.GetWeightPathConnection(samePath, num, normalizedDepthDifference);
							}
						}
					}
				}
			}
		}

		private class TilePlacementResultProxy
		{
			public TilePlacementResult result;

			public TileProxy tileProxy;

			public DoorwayProxy previousDoorway;

			public DoorwayProxy nextDoorway;

			public TilePlacementResultProxy(TilePlacementResult result)
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				this.result = result;
				tileProxy = null;
				previousDoorway = null;
				nextDoorway = null;
			}

			public TilePlacementResultProxy(TilePlacementResult result, TileProxy tile, DoorwayProxy previousDoorway, DoorwayProxy nextDoorway)
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				this.result = result;
				tileProxy = tile;
				this.previousDoorway = previousDoorway;
				this.nextDoorway = nextDoorway;
			}
		}

		public static MainPathExtender currentMainPathExtender;

		internal static HDRenderPipelineAsset previousHDRPAsset;

		internal static HDRenderPipelineAsset newHDRPAsset;

		private static Dictionary<TileProxy, int> tileProxyMainPath = new Dictionary<TileProxy, int>();

		public static Stopwatch GenerateBranchBoostedPathsStopWatch = new Stopwatch();

		public static float GenerateBranchBoostedPathsTime = 0f;

		public static Stopwatch GetTileResultStopwatch = new Stopwatch();

		public static float GetTileResultTime = 0f;

		public static Stopwatch DoorwayPairStopwatch = new Stopwatch();

		public static float DoorwayPairTime = 0f;

		public static Stopwatch CalculateWeightStopwatch = new Stopwatch();

		public static float CalculateWeightTime = 0f;

		public static DunGenExtender Instance { get; internal set; }

		public static DunGenExtenderProperties Properties { get; internal set; }

		public static bool Active { get; internal set; }

		public static bool ActiveAlternative { get; internal set; }

		public static void SetCurrentMainPathExtender(int mainPathIndex)
		{
			currentMainPathExtender = Properties.MainPathProperties.GetMainPathDetails(mainPathIndex);
		}

		public static GraphLine GetLineAtDepth(DungeonFlow flow, float depth)
		{
			if (!Active)
			{
				return flow.GetLineAtDepth(depth);
			}
			List<GraphLine> lines = MainPathExtender.GetLines(currentMainPathExtender, flow);
			return GetLineAtDepthHelper(lines, depth);
		}

		public static GraphLine GetLineAtDepthHelper(List<GraphLine> graphLines, float normalizedDepth)
		{
			normalizedDepth = Mathf.Clamp(normalizedDepth, 0f, 1f);
			if (normalizedDepth == 0f)
			{
				return graphLines[0];
			}
			if (normalizedDepth == 1f)
			{
				return graphLines[graphLines.Count - 1];
			}
			foreach (GraphLine graphLine in graphLines)
			{
				if (normalizedDepth >= graphLine.Position && normalizedDepth < graphLine.Position + graphLine.Length)
				{
					return graphLine;
				}
			}
			Debug.LogError((object)("GetLineAtDepth was unable to find a line at depth " + normalizedDepth + ". This shouldn't happen."));
			return null;
		}

		public static List<GraphNode> GetNodes(DungeonFlow flow)
		{
			if (!Active)
			{
				return flow.Nodes;
			}
			return MainPathExtender.GetNodes(currentMainPathExtender, flow);
		}

		public static BranchMode GetBranchMode(DungeonFlow flow)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (!Active)
			{
				return flow.BranchMode;
			}
			return MainPathExtender.GetBranchMode(currentMainPathExtender, flow);
		}

		public static IntRange GetBranchCount(DungeonFlow flow)
		{
			if (!Active)
			{
				return flow.BranchCount;
			}
			return MainPathExtender.GetBranchCount(currentMainPathExtender, flow);
		}

		public static IntRange GetLength(DungeonFlow flow)
		{
			if (!Active)
			{
				return flow.Length;
			}
			return MainPathExtender.GetLength(currentMainPathExtender, flow);
		}

		public static void Activate(DungeonGenerator generator, DunGenExtender extender)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			Instance = extender;
			Active = true;
			ActiveAlternative = true;
			DunGenExtenderProperties dunGenExtenderProperties = extender.Properties.Copy(extender.Version);
			EventCallbackScenario param = new EventCallbackScenario(Object.op_Implicit((Object)(object)DevDebugManager.Instance));
			Instance.Events.OnModifyDunGenExtenderProperties.Invoke(dunGenExtenderProperties, param);
			dunGenExtenderProperties.NormalNodeArchetypesProperties.SetupProperties(generator);
			Properties = dunGenExtenderProperties;
			if (Properties.DungeonBoundsProperties.UseDungeonBounds)
			{
				generator.DebugRender = true;
				generator.RestrictDungeonToBounds = true;
				Bounds val = (generator.TilePlacementBounds = Properties.DungeonBoundsProperties.GetDungeonBounds(generator.LengthMultiplier));
				Plugin.logger.LogDebug((object)$"Dungeon Bounds: {val}");
			}
			if (Properties.MiscellaneousProperties.UseMaxShadowsRequestUpdate)
			{
				Plugin.logger.LogDebug((object)$"Updating HDRP asset: setting max shadows request to {Properties.MiscellaneousProperties.MaxShadowsRequestCount}");
				try
				{
					RenderPipelineAsset renderPipeline = QualitySettings.renderPipeline;
					previousHDRPAsset = (HDRenderPipelineAsset)(object)((renderPipeline is HDRenderPipelineAsset) ? renderPipeline : null);
					newHDRPAsset = Object.Instantiate<HDRenderPipelineAsset>(previousHDRPAsset);
					RenderPipelineSettings currentPlatformRenderPipelineSettings = newHDRPAsset.currentPlatformRenderPipelineSettings;
					currentPlatformRenderPipelineSettings.hdShadowInitParams.maxScreenSpaceShadowSlots = Properties.MiscellaneousProperties.MaxShadowsRequestCount;
					newHDRPAsset.currentPlatformRenderPipelineSettings = currentPlatformRenderPipelineSettings;
					QualitySettings.renderPipeline = (RenderPipelineAsset)(object)newHDRPAsset;
				}
				catch (Exception ex)
				{
					Plugin.logger.LogError((object)"Failed to update HDRP asset");
					Plugin.logger.LogError((object)ex.ToString());
				}
			}
			DoorwayManager.ResetList();
			DoorwayManager.onMainEntranceTeleportSpawnedEvent.ClearTemporaryActionList();
		}

		public static void Deactivate()
		{
			Instance = null;
			Properties = null;
			Active = false;
			ActiveAlternative = false;
			if (Object.op_Implicit((Object)(object)previousHDRPAsset) && (Object)(object)QualitySettings.renderPipeline == (Object)(object)newHDRPAsset)
			{
				Plugin.logger.LogDebug((object)"Restoring original HDRP asset");
				QualitySettings.renderPipeline = (RenderPipelineAsset)(object)previousHDRPAsset;
				previousHDRPAsset = null;
				newHDRPAsset = null;
			}
		}

		public static int GetMainPathIndexFromTileProxy(TileProxy tileProxy)
		{
			return tileProxyMainPath[tileProxy];
		}

		private static void AddTileProxyToMainPathDictionary(IEnumerable<TileProxy> tileProxies, int index)
		{
			float num = tileProxies.Last().Placement.PathDepth;
			foreach (TileProxy tileProxy in tileProxies)
			{
				tileProxyMainPath.Add(tileProxy, index);
				tileProxy.Placement.NormalizedPathDepth = (float)tileProxy.Placement.PathDepth / num;
			}
		}

		public static IEnumerator GenerateAlternativeMainPaths(DungeonGenerator gen)
		{
			if (!Active)
			{
				ActiveAlternative = false;
				yield return gen.Wait(gen.GenerateBranchPaths());
				ActiveAlternative = true;
				yield break;
			}
			int altCount = Properties.MainPathProperties.MainPathCount - 1;
			tileProxyMainPath.Clear();
			GameObject mainRoomTilePrefab = Properties.MainPathProperties.MainRoomTilePrefab;
			DunGenExtenderProperties.CopyNodeBehaviour copyNodeBehaviour = Properties.MainPathProperties.CopyNodeBehaviour;
			if (altCount <= 0)
			{
				yield return gen.Wait(GenerateBranchPaths(gen, null, $"MainPathCount being {altCount + 1}", (LogLevel)16));
				yield break;
			}
			if ((Object)(object)mainRoomTilePrefab == (Object)null)
			{
				yield return gen.Wait(GenerateBranchPaths(gen, null, "MainRoomTilePrefab being null", (LogLevel)4));
				yield break;
			}
			List<List<TileProxy>> allMainPathTiles = new List<List<TileProxy>>();
			List<TileProxy> firstMainPathTiles = gen.proxyDungeon.MainPathTiles.ToList();
			allMainPathTiles.Add(firstMainPathTiles);
			AddTileProxyToMainPathDictionary(firstMainPathTiles, 0);
			TileProxy mainRoom = ((IEnumerable<TileProxy>)gen.proxyDungeon.MainPathTiles).FirstOrDefault((Func<TileProxy, bool>)((TileProxy t) => (Object)(object)t.Prefab == (Object)(object)mainRoomTilePrefab));
			if (mainRoom == null)
			{
				yield return gen.Wait(GenerateBranchPaths(gen, null, "MainRoomTilePrefab not spawning on the main path", (LogLevel)4));
				yield break;
			}
			int mainRoomStartingLengthIndex = mainRoom.Placement.Depth + 1;
			Plugin.logger.LogDebug((object)$"Main Room Length Index: {mainRoomStartingLengthIndex}");
			gen.ChangeStatus((GenerationStatus)3);
			int b = 0;
			while (b < altCount)
			{
				SetCurrentMainPathExtender(b + 1);
				RandomizeLineArchetypes(gen, randomizeMainPath: true);
				TileProxy previousTile = mainRoom;
				int targetLength = Mathf.RoundToInt((float)GetLength(gen.DungeonFlow).GetRandom(gen.RandomStream) * gen.LengthMultiplier);
				List<DungeonArchetype> archetypes = new List<DungeonArchetype>(targetLength);
				List<TileProxy> newMainPathTiles = new List<TileProxy>();
				List<GraphNode> nodesSorted = (from n in GetNodes(gen.DungeonFlow)
					orderby n.Position
					select n).ToList();
				int startingNodeIndex;
				switch (copyNodeBehaviour)
				{
				case DunGenExtenderProperties.CopyNodeBehaviour.CopyFromNodeList:
				{
					int index = nodesSorted.FindIndex((GraphNode n) => n.TileSets.SelectMany((TileSet t) => t.TileWeights.Weights).Any((GameObjectChance t) => (Object)(object)t.Value == (Object)(object)mainRoomTilePrefab));
					if (index == -1)
					{
						yield return gen.Wait(GenerateBranchPaths(gen, mainRoom, "CopyNodeBehaviour being CopyFromNodeList AND MainRoomTilePrefab not existing in the Nodes' tilesets", (LogLevel)4));
						yield break;
					}
					startingNodeIndex = index + 1;
					break;
				}
				case DunGenExtenderProperties.CopyNodeBehaviour.CopyFromMainPathPosition:
				{
					float lineDepthRatio = Mathf.Clamp01(1f / (float)(targetLength - 1));
					startingNodeIndex = nodesSorted.FindIndex((GraphNode n) => n.Position >= lineDepthRatio);
					break;
				}
				default:
					Plugin.logger.LogFatal((object)$"{copyNodeBehaviour} is not yet defined. Really really bad");
					startingNodeIndex = -1;
					break;
				}
				IEnumerable<GraphNode> nodes = nodesSorted.Skip(startingNodeIndex);
				List<GraphNode> nodesVisited = new List<GraphNode>(nodes.Count());
				MainRoomDoorwayGroups.ModifyGroupBasedOnBehaviour(mainRoom, b + 1);
				bool reachedLastNode = false;
				GraphNode lastNode = nodes.ElementAt(nodes.Count() - 1);
				int t2 = mainRoomStartingLengthIndex;
				int num;
				while (t2 < targetLength && !reachedLastNode)
				{
					float lineDepthRatio2 = Mathf.Clamp01((float)t2 / (float)(targetLength - 1));
					GraphLine lineAtDepth = GetLineAtDepth(gen.DungeonFlow, lineDepthRatio2);
					if (lineAtDepth == null)
					{
						yield return gen.Wait(gen.InnerGenerate(true));
						yield break;
					}
					if (lineAtDepth != gen.previousLineSegment)
					{
						gen.currentArchetype = lineAtDepth.GetRandomArchetype(gen.RandomStream, (IList<DungeonArchetype>)archetypes);
						gen.previousLineSegment = lineAtDepth;
					}
					GraphNode graphNode = null;
					foreach (GraphNode g in nodes)
					{
						if (lineDepthRatio2 >= g.Position && !nodesVisited.Contains(g))
						{
							graphNode = g;
							nodesVisited.Add(g);
							break;
						}
					}
					DungeonArchetype archetype;
					List<TileSet> useableTileSets;
					if (graphNode != null)
					{
						archetype = ModifyMainBranchNodeArchetype(null, graphNode, gen.RandomStream);
						useableTileSets = graphNode.TileSets;
						if (graphNode == lastNode)
						{
							reachedLastNode = true;
						}
					}
					else
					{
						archetype = gen.currentArchetype;
						useableTileSets = archetype.TileSets;
					}
					TileProxy tileProxy = gen.AddTile(previousTile, (IEnumerable<TileSet>)useableTileSets, lineDepthRatio2, archetype, (TilePlacementResult)0);
					if (tileProxy == null)
					{
						string prevName = ((previousTile != null) ? ((Object)previousTile.Prefab).name : "NULL");
						string archetypeName = (Object.op_Implicit((Object)(object)archetype) ? ((Object)archetype).name : "NULL");
						string tileSetNames = string.Join(", ", useableTileSets);
						Plugin.logger.LogDebug((object)$"Alt. main branch gen failed at Branch {b} (Length: {t2}, Ratio: {lineDepthRatio2})");
						Plugin.logger.LogDebug((object)("Prev tile: " + prevName + "\nArchetype: " + archetypeName + "\nTilesets: " + tileSetNames));
						Plugin.logger.LogDebug((object)$"Reason: {DungeonGeneratorPatch.lastTilePlacementResult}");
						if (previousTile != null)
						{
							string availableDoorways = string.Join(",", previousTile.UnusedDoorways);
							string usedDoorways = string.Join(",", previousTile.UsedDoorways);
							Plugin.logger.LogDebug((object)("Available Doorways: " + availableDoorways));
							Plugin.logger.LogDebug((object)("Used Doorways: " + usedDoorways));
						}
						yield return gen.Wait(gen.InnerGenerate(true));
						yield break;
					}
					if (reachedLastNode || lineDepthRatio2 >= 1f)
					{
						Plugin.logger.LogDebug((object)$"Alt. main branch at {b} ended with {((Object)tileProxy.PrefabTile).name}");
					}
					tileProxy.Placement.BranchDepth = t2;
					tileProxy.Placement.NormalizedBranchDepth = lineDepthRatio2;
					if (graphNode != null)
					{
						tileProxy.Placement.GraphNode = graphNode;
						tileProxy.Placement.GraphLine = null;
					}
					else
					{
						tileProxy.Placement.GraphNode = null;
						tileProxy.Placement.GraphLine = lineAtDepth;
					}
					previousTile = tileProxy;
					newMainPathTiles.Add(tileProxy);
					if (gen.ShouldSkipFrame(true))
					{
						yield return gen.GetRoomPause();
					}
					num = t2 + 1;
					t2 = num;
				}
				AddTileProxyToMainPathDictionary(newMainPathTiles, b + 1);
				allMainPathTiles.Add(newMainPathTiles);
				num = b + 1;
				b = num;
			}
			MainRoomDoorwayGroups.RemoveFakeDoorwayProxies(mainRoom);
			ActiveAlternative = false;
			Plugin.logger.LogDebug((object)$"Created {altCount} alt. paths, creating branches now");
			gen.ChangeStatus((GenerationStatus)4);
			int b2 = 0;
			while (b2 < altCount + 1)
			{
				Plugin.logger.LogDebug((object)$"Branch {b2}");
				SetCurrentMainPathExtender(b2);
				RandomizeLineArchetypes(gen, randomizeMainPath: false);
				gen.proxyDungeon.MainPathTiles = allMainPathTiles[b2];
				if (Properties.BranchPathMultiSimulationProperties.UseBranchPathMultiSim)
				{
					GenerateBranchBoostedPathsStopWatch.Reset();
					GenerateBranchBoostedPathsStopWatch.Start();
					yield return gen.Wait(GenerateMultiBranchPaths(gen));
					GenerateBranchBoostedPathsStopWatch.Stop();
					GenerateBranchBoostedPathsTime += (float)GenerateBranchBoostedPathsStopWatch.Elapsed.TotalMilliseconds;
				}
				else
				{
					yield return gen.Wait(gen.GenerateBranchPaths());
				}
				int num = b2 + 1;
				b2 = num;
			}
			ActiveAlternative = true;
			gen.proxyDungeon.MainPathTiles = allMainPathTiles[0];
			AddForcedTiles(gen);
		}

		private static IEnumerator GenerateBranchPaths(DungeonGenerator gen, TileProxy mainRoom, string message, LogLevel logLevel)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			Plugin.logger.Log(logLevel, (object)("Switching to default dungeon branch generation: " + message));
			ActiveAlternative = false;
			SetCurrentMainPathExtender(0);
			if (mainRoom != null)
			{
				MainRoomDoorwayGroups.RemoveFakeDoorwayProxies(mainRoom);
			}
			yield return gen.Wait(gen.GenerateBranchPaths());
			ActiveAlternative = true;
			AddForcedTiles(gen);
		}

		public static void FixDoorwaysToAllFloors(TileProxy mainRoom, MainRoomDoorwayGroups doorwayGroups)
		{
			List<Doorway> doorwayListFirst = doorwayGroups.doorwayListFirst;
			if (doorwayListFirst == null)
			{
				return;
			}
			foreach (DoorwayProxy usedDoorway in mainRoom.UsedDoorways)
			{
				if (usedDoorway.ConnectedDoorway.Index == int.MaxValue && !doorwayListFirst.Contains(usedDoorway.DoorwayComponent))
				{
					usedDoorway.ConnectedDoorway = null;
				}
			}
		}

		public static IEnumerator GenerateMultiBranchPaths(DungeonGenerator gen)
		{
			gen.ChangeStatus((GenerationStatus)4);
			int[] mainPathBranches = new int[gen.proxyDungeon.MainPathTiles.Count];
			BranchCountHelper.ComputeBranchCounts(gen.DungeonFlow, gen.RandomStream, gen.proxyDungeon, ref mainPathBranches);
			int b = 0;
			while (b < mainPathBranches.Length)
			{
				TileProxy tile = gen.proxyDungeon.MainPathTiles[b];
				int branchCount = mainPathBranches[b];
				int num;
				if (!((Object)(object)tile.Placement.Archetype == (Object)null) && branchCount != 0)
				{
					for (int i = 0; i < branchCount; i = num)
					{
						List<BranchPathProxy> pathProxys = new List<BranchPathProxy>();
						for (int x2 = 0; x2 < Properties.BranchPathMultiSimulationProperties.SimulationCount; x2 = num)
						{
							BranchPathProxy currentPathProxy = new BranchPathProxy(gen, tile);
							TileProxy previousTile = tile;
							int branchDepth = tile.Placement.Archetype.BranchingDepth.GetRandom(gen.RandomStream);
							for (int depth = 0; depth < branchDepth; depth = num)
							{
								List<TileSet> useableTileSets = ((depth != branchDepth - 1 || !tile.Placement.Archetype.GetHasValidBranchCapTiles()) ? tile.Placement.Archetype.TileSets : (((int)tile.Placement.Archetype.BranchCapType != 0) ? tile.Placement.Archetype.TileSets.Concat(tile.Placement.Archetype.BranchCapTileSets).ToList() : tile.Placement.Archetype.BranchCapTileSets));
								float normalizedDepth = ((branchDepth <= 1) ? 1f : ((float)depth / (float)(branchDepth - 1)));
								GetTileResultStopwatch.Reset();
								GetTileResultStopwatch.Start();
								TilePlacementResultProxy tileResult = GetTileResult(gen, currentPathProxy, previousTile, useableTileSets, normalizedDepth, tile.Placement.Archetype);
								GetTileResultStopwatch.Stop();
								GetTileResultTime += (float)GetTileResultStopwatch.Elapsed.TotalMilliseconds;
								TileProxy tileProxy = tileResult.tileProxy;
								if (tileProxy == null)
								{
									break;
								}
								currentPathProxy.list.Add(tileResult);
								tileProxy.Placement.BranchDepth = depth;
								tileProxy.Placement.NormalizedBranchDepth = normalizedDepth;
								previousTile = tileProxy;
								num = depth + 1;
							}
							if (currentPathProxy.list.Count == 0)
							{
								break;
							}
							CalculateWeightStopwatch.Reset();
							CalculateWeightStopwatch.Start();
							currentPathProxy.CalculateWeight(gen);
							CalculateWeightStopwatch.Stop();
							CalculateWeightTime += (float)CalculateWeightStopwatch.Elapsed.TotalMilliseconds;
							pathProxys.Add(currentPathProxy);
							num = x2 + 1;
						}
						BranchPathProxy bestPath = pathProxys.OrderByDescending((BranchPathProxy p) => p.weight).FirstOrDefault();
						if (bestPath != null)
						{
							foreach (TilePlacementResultProxy item in bestPath.list)
							{
								MakeTileProxyConnection(gen, item);
								item.tileProxy.Placement.GraphNode = item.previousDoorway.TileProxy.Placement.GraphNode;
								item.tileProxy.Placement.GraphLine = item.previousDoorway.TileProxy.Placement.GraphLine;
							}
							gen.injectedTiles = bestPath.injectedTiles;
							gen.tilesPendingInjection = bestPath.tilesPendingInjection;
							AddTileProxyToMainPathDictionary(bestPath.list.Select((TilePlacementResultProxy x) => x.tileProxy), bestPath.mainPathIndex);
							if (gen.ShouldSkipFrame(true))
							{
								yield return gen.GetRoomPause();
							}
						}
						num = i + 1;
					}
				}
				num = b + 1;
				b = num;
			}
		}

		private static TilePlacementResultProxy GetTileResult(DungeonGenerator gen, BranchPathProxy pathProxy, TileProxy attachTo, IEnumerable<TileSet> useableTileSets, float normalizedDepth, DungeonArchetype archetype)
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Expected O, but got Unknown
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Invalid comparison between Unknown and I4
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Invalid comparison between Unknown and I4
			InjectedTile val = null;
			int index = -1;
			if (pathProxy.tilesPendingInjection != null)
			{
				float num = (float)attachTo.Placement.PathDepth / (float)gen.targetLength - 1f;
				for (int i = 0; i < pathProxy.tilesPendingInjection.Count; i++)
				{
					InjectedTile val2 = pathProxy.tilesPendingInjection[i];
					if (val2.ShouldInjectTileAtPoint(false, num, normalizedDepth))
					{
						val = val2;
						index = i;
						break;
					}
				}
			}
			IEnumerable<GameObjectChance> collection = ((val == null) ? useableTileSets.SelectMany((TileSet t) => t.TileWeights.Weights) : new List<GameObjectChance>(val.TileSet.TileWeights.Weights));
			bool value = attachTo.PrefabTile.AllowRotation;
			if (gen.OverrideAllowTileRotation)
			{
				value = gen.AllowTileRotation;
			}
			DoorwayPairFinder val3 = new DoorwayPairFinder();
			val3.DungeonFlow = gen.DungeonFlow;
			val3.RandomStream = gen.RandomStream;
			val3.Archetype = archetype;
			val3.GetTileTemplateDelegate = new GetTileTemplateDelegate(gen.GetTileTemplate);
			val3.IsOnMainPath = false;
			val3.NormalizedDepth = normalizedDepth;
			val3.PreviousTile = attachTo;
			val3.UpVector = gen.UpVector;
			val3.AllowRotation = value;
			val3.TileWeights = new List<GameObjectChance>(collection);
			val3.IsTileAllowedPredicate = (TileMatchDelegate)delegate(TileProxy prev, TileProxy next, ref float weight)
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_008a: Expected I4, but got Unknown
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
				bool flag = prev != null && (Object)(object)next.Prefab == (Object)(object)prev.Prefab;
				TileRepeatMode val4 = (TileRepeatMode)0;
				if (gen.OverrideRepeatMode)
				{
					val4 = gen.RepeatMode;
				}
				else if (next != null)
				{
					val4 = next.PrefabTile.RepeatMode;
				}
				TileRepeatMode val5 = val4;
				TileRepeatMode val6 = val5;
				return (int)val6 switch
				{
					0 => true, 
					1 => !flag, 
					2 => !gen.proxyDungeon.AllTiles.Where((TileProxy x) => (Object)(object)x.Prefab == (Object)(object)next.Prefab).Any(), 
					_ => throw new NotImplementedException($"TileRepeatMode {val4} is not implemented"), 
				};
			};
			int? num2 = (gen.UseMaximumPairingAttempts ? new int?(gen.MaxPairingAttempts) : null);
			DoorwayPairStopwatch.Reset();
			DoorwayPairStopwatch.Start();
			Queue<DoorwayPair> doorwayPairs = val3.GetDoorwayPairs(num2);
			DoorwayPairStopwatch.Stop();
			DoorwayPairTime += (float)DoorwayPairStopwatch.Elapsed.TotalMilliseconds;
			TilePlacementResultProxy tilePlacementResultProxy = new TilePlacementResultProxy((TilePlacementResult)3);
			while (doorwayPairs.Count > 0)
			{
				DoorwayPair pair = doorwayPairs.Dequeue();
				tilePlacementResultProxy = TryPlaceTileResult(gen, pathProxy, pair, archetype);
				if ((int)tilePlacementResultProxy.result == 0)
				{
					break;
				}
			}
			if ((int)tilePlacementResultProxy.result == 0)
			{
				if (val != null)
				{
					TileProxy tileProxy = tilePlacementResultProxy.tileProxy;
					tileProxy.Placement.InjectionData = val;
					pathProxy.injectedTiles[tileProxy] = val;
					pathProxy.tilesPendingInjection.RemoveAt(index);
				}
				return tilePlacementResultProxy;
			}
			return new TilePlacementResultProxy((TilePlacementResult)3);
		}

		private static TilePlacementResultProxy TryPlaceTileResult(DungeonGenerator gen, BranchPathProxy pathProxy, DoorwayPair pair, DungeonArchetype archetype)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			TileProxy nextTemplate = ((DoorwayPair)(ref pair)).NextTemplate;
			DoorwayProxy previousDoorway = ((DoorwayPair)(ref pair)).PreviousDoorway;
			if (nextTemplate == null)
			{
				return new TilePlacementResultProxy((TilePlacementResult)4);
			}
			int index = ((DoorwayPair)(ref pair)).NextTemplate.Doorways.IndexOf(((DoorwayPair)(ref pair)).NextDoorway);
			TileProxy val = new TileProxy(nextTemplate);
			val.Placement.IsOnMainPath = false;
			val.Placement.Archetype = archetype;
			val.Placement.TileSet = ((DoorwayPair)(ref pair)).NextTileSet;
			if (previousDoorway != null)
			{
				DoorwayProxy val2 = val.Doorways[index];
				val.PositionBySocket(val2, previousDoorway);
				Bounds bounds = val.Placement.Bounds;
				if (gen.RestrictDungeonToBounds && !UnityUtil.Contains(gen.TilePlacementBounds, bounds))
				{
					return new TilePlacementResultProxy((TilePlacementResult)8);
				}
				if (IsCollidingWithAnyTileAndTileResult(gen, pathProxy, val, previousDoorway.TileProxy))
				{
					return new TilePlacementResultProxy((TilePlacementResult)6);
				}
			}
			if (val == null)
			{
				return new TilePlacementResultProxy((TilePlacementResult)7);
			}
			val.Placement.PathDepth = ((DoorwayPair)(ref pair)).PreviousTile.Placement.PathDepth;
			val.Placement.NormalizedPathDepth = ((DoorwayPair)(ref pair)).PreviousTile.Placement.NormalizedPathDepth;
			val.Placement.BranchDepth = ((!((DoorwayPair)(ref pair)).PreviousTile.Placement.IsOnMainPath) ? (((DoorwayPair)(ref pair)).PreviousTile.Placement.BranchDepth + 1) : 0);
			return new TilePlacementResultProxy((TilePlacementResult)0, val, previousDoorway, val.Doorways[index]);
		}

		private static bool IsCollidingWithAnyTileAndTileResult(DungeonGenerator gen, BranchPathProxy pathProxy, TileProxy newTile, TileProxy previousTile)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			foreach (TileProxy item in gen.proxyDungeon.AllTiles.Concat(pathProxy.list.Select((TilePlacementResultProxy t) => t.tileProxy)))
			{
				bool flag = previousTile == item;
				float num = (flag ? gen.OverlapThreshold : (0f - gen.Padding));
				if (gen.DisallowOverhangs && !flag)
				{
					if (newTile.IsOverlappingOrOverhanging(item, gen.UpDirection, num))
					{
						return true;
					}
				}
				else if (newTile.IsOverlapping(item, num))
				{
					return true;
				}
			}
			return false;
		}

		private static void MakeTileProxyConnection(DungeonGenerator gen, TilePlacementResultProxy proxy)
		{
			if (proxy.previousDoorway != null)
			{
				gen.proxyDungeon.MakeConnection(proxy.previousDoorway, proxy.nextDoorway);
			}
			gen.proxyDungeon.AddTile(proxy.tileProxy);
		}

		public static void AddForcedTiles(DungeonGenerator gen)
		{
			if (!Properties.AdditionalTilesProperties.UseAdditionalTiles)
			{
				return;
			}
			List<AdditionalTileSetList> list = Properties.AdditionalTilesProperties.AdditionalTileSets.ToList();
			while (list.Count > 0)
			{
				AdditionalTileSetList item = list[list.Count - 1];
				IOrderedEnumerable<(TileProxy, double)> orderedEnumerable = from pair in gen.proxyDungeon.AllTiles.Select(delegate(TileProxy t)
					{
						float num = item.DepthWeightScale.Evaluate(t.Placement.NormalizedDepth);
						float num2 = (t.Placement.IsOnMainPath ? item.MainPathWeight : item.BranchPathWeight);
						return (t, (double)(num * num2) * gen.RandomStream.NextDouble());
					})
					where pair.Item2 > 0.0
					orderby pair.Item2
					select pair;
				foreach (var item3 in orderedEnumerable)
				{
					TileProxy item2 = item3.Item1;
					TileProxy val = gen.AddTile(item2, (IEnumerable<TileSet>)item.TileSets, item2.Placement.NormalizedDepth, (DungeonArchetype)null, (TilePlacementResult)0);
					if (val == null)
					{
						continue;
					}
					val.Placement.BranchDepth = item2.Placement.BranchDepth;
					val.Placement.NormalizedBranchDepth = item2.Placement.NormalizedDepth;
					val.Placement.GraphNode = item2.Placement.GraphNode;
					val.Placement.GraphLine = item2.Placement.GraphLine;
					Plugin.logger.LogDebug((object)("Forcefully added tile " + ((Object)val.Prefab).name));
					break;
				}
				list.RemoveAt(list.Count - 1);
			}
			Plugin.logger.LogDebug((object)"Forcefully added all tiles");
		}

		public static void RandomizeLineArchetypes(DungeonGenerator gen, bool randomizeMainPath)
		{
			if (!Properties.LineRandomizerProperties.UseLineRandomizer)
			{
				return;
			}
			DungeonFlow dungeonFlow = Instance.DungeonFlow;
			List<GraphLine> lines = dungeonFlow.Lines;
			Dictionary<TileSet, int> dictionary = new Dictionary<TileSet, int>();
			foreach (TileSet tileSet in Properties.LineRandomizerProperties.TileSets)
			{
				dictionary.Add(tileSet, 0);
			}
			foreach (DungeonArchetype archetype in Properties.LineRandomizerProperties.Archetypes)
			{
				List<TileSet> targetTileSet = (randomizeMainPath ? archetype.TileSets : archetype.BranchCapTileSets);
				RandomizeArchetype(gen, targetTileSet, dictionary);
			}
		}

		public static void RandomizeArchetype(DungeonGenerator gen, List<TileSet> targetTileSet, Dictionary<TileSet, int> tilesetsUsed)
		{
			IEnumerable<TileSet> enumerable = Properties.LineRandomizerProperties.TileSets.OrderBy((TileSet t) => (double)tilesetsUsed[t] + gen.RandomStream.NextDouble()).Take(Properties.LineRandomizerProperties.TileSetsTakeCount);
			int num = targetTileSet.Count - 1;
			using IEnumerator<TileSet> enumerator = enumerable.GetEnumerator();
			while (enumerator.MoveNext())
			{
				TileSet key = (targetTileSet[num] = enumerator.Current);
				num--;
				tilesetsUsed[key]++;
			}
		}

		public static DungeonArchetype ModifyMainBranchNodeArchetype(DungeonArchetype archetype, GraphNode node, RandomStream randomStream)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			if (!Active)
			{
				return archetype;
			}
			if (Properties.NormalNodeArchetypesProperties.AddArchetypesToNormalNodes && (int)node.NodeType == 0)
			{
				return Properties.NormalNodeArchetypesProperties.GetRandomArchetype(node.Label, randomStream);
			}
			return archetype;
		}

		public static bool AllowRetryStop(bool defaultState)
		{
			return defaultState || DevDebugManager.IsActive;
		}
	}
	internal static class DoorwaySistersRule
	{
		public class Data
		{
			public DoorwaySisters info;

			public List<DoorwayProxy> proxies;
		}

		public static Dictionary<Doorway, Data> doorwayDictionary;

		public static Dictionary<DoorwayProxy, Data> doorwayProxyDictionary;

		public static void UpdateCache(IEnumerable<DoorwayProxy> list)
		{
			if (!DunGenPlusGenerator.Active || !DunGenPlusGenerator.Properties.MiscellaneousProperties.UseDoorwaySisters)
			{
				return;
			}
			Plugin.logger.LogDebug((object)"Updating DoorwayProxy cache for DoorwaySistersRule");
			doorwayDictionary = new Dictionary<Doorway, Data>();
			doorwayProxyDictionary = new Dictionary<DoorwayProxy, Data>();
			foreach (DoorwayProxy item in list)
			{
				Doorway doorwayComponent = item.DoorwayComponent;
				if (doorwayDictionary.TryGetValue(doorwayComponent, out var value))
				{
					value.proxies.Add(item);
					doorwayProxyDictionary.Add(item, value);
					continue;
				}
				List<DoorwayProxy> list2 = new List<DoorwayProxy>();
				list2.Add(item);
				Data value2 = new Data
				{
					info = ((Component)doorwayComponent).GetComponent<DoorwaySisters>(),
					proxies = list2
				};
				doorwayProxyDictionary.Add(item, value2);
				doorwayDictionary.Add(item.DoorwayComponent, value2);
			}
		}

		public static bool CanDoorwaysConnect(bool result, TileProxy tileA, TileProxy tileB, DoorwayProxy doorwayA, DoorwayProxy doorwayB)
		{
			if (!result)
			{
				return false;
			}
			if (!DunGenPlusGenerator.Active || !DunGenPlusGenerator.Properties.MiscellaneousProperties.UseDoorwaySisters)
			{
				return true;
			}
			DoorwaySisters info = doorwayProxyDictionary[doorwayA].info;
			DoorwaySisters info2 = doorwayProxyDictionary[doorwayB].info;
			if (CheckIfSisterActive(info, tileB))
			{
				return false;
			}
			if (CheckIfSisterActive(info2, tileA))
			{
				return false;
			}
			return true;
		}

		public static bool CheckIfSisterActive(DoorwaySisters info, TileProxy targetTile)
		{
			if ((Object)(object)info == (Object)null || info.sisters == null)
			{
				return false;
			}
			foreach (Doorway sister in info.sisters)
			{
				List<DoorwayProxy> proxies = doorwayDictionary[sister].proxies;
				foreach (DoorwayProxy item in proxies)
				{
					if (item.ConnectedDoorway != null && item.ConnectedDoorway.TileProxy == targetTile)
					{
						return true;
					}
				}
			}
			return false;
		}
	}
}
namespace DunGenPlus.DevTools
{
	internal class DevDebugManager : MonoBehaviour
	{
		[Header("References")]
		public RuntimeDungeon dungeon;

		public GameObject devCamera;

		public BasePanel[] panels;

		public RectTransform canvasRectTransform;

		public TMP_Dropdown dungeonFlowSelectionDropDown;

		private ExtendedDungeonFlow[] dungeonFlows;

		internal ExtendedDungeonFlow selectedExtendedDungeonFlow;

		internal DungeonFlow selectedDungeonFlow;

		internal DungeonFlowCacheAssets selectedAssetCache;

		internal Dictionary<DungeonFlow, DungeonFlowCacheAssets> cacheDictionary = new Dictionary<DungeonFlow, DungeonFlowCacheAssets>();

		public TextMeshProUGUI statusTextMesh;

		public TextMeshProUGUI statsTextMesh;

		private GameObject disabledGameObject;

		private RoundManager fakeRoundManager;

		private Camera lastMainCamera;

		private Vector3 lastCameraPosition;

		private Quaternion lastCameraRotation;

		private Vector2 cameraYRange;

		public bool canvasExtended;

		private float canvasWidthTarget;

		[Header("UI Prefabs")]
		[Header("UI")]
		public GameObject headerUIPrefab;

		public GameObject textUIPrefab;

		public GameObject spaceUIPrefab;

		public GameObject verticalLayoutUIPrefab;

		[Header("Input Fields")]
		public GameObject intInputFieldPrefab;

		public GameObject floatInputFieldPrefab;

		public GameObject boolInputFieldPrefab;

		public GameObject stringInputFieldPrefab;

		public GameObject vector3InputFieldPrefab;

		public GameObject intRangeInputFieldPrefab;

		public GameObject floatRangeInputFieldPrefab;

		public GameObject intSliderFieldPrefab;

		[Header("Special Fields")]
		public GameObject listUIPrefab;

		public GameObject optionsUIPrefab;

		public static DevDebugManager Instance { get; private set; }

		public static bool IsActive => (Object)(object)Instance != (Object)null;

		private void Awake()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
			CacheMainCamera();
			BeginDevCamera();
			GetAllDungeonFlows();
			BasePanel[] array = panels;
			foreach (BasePanel basePanel in array)
			{
				basePanel.AwakeCall();
			}
			OpenPanel(0);
			UpdatePanels();
			dungeon.Generator.OnGenerationStatusChanged += new GenerationStatusDelegate(OnDungeonFinished);
			disabledGameObject = new GameObject("Disabled GOBJ");
			disabledGameObject.SetActive(false);
			disabledGameObject.transform.SetParent(((Component)this).transform);
			cameraYRange = new Vector2(devCamera.transform.position.y - 200f, devCamera.transform.position.y);
			canvasExtended = false;
			canvasWidthTarget = 440f;
		}

		private void OnDestroy()
		{
			Instance = null;
			MainPanel.Instance = null;
			DunFlowPanel.Instance = null;
			DunGenPlusPanel.Instance = null;
			Cursor.lockState = (CursorLockMode)1;
			Cursor.visible = false;
			EndDevCamera();
		}

		private unsafe void Update()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: 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_0158: Unknown result type (might be due to invalid IL or missing references)
			Vector2 sizeDelta = canvasRectTransform.sizeDelta;
			sizeDelta.x = Mathf.Lerp(sizeDelta.x, canvasWidthTarget, Time.deltaTime * 10f);
			canvasRectTransform.sizeDelta = sizeDelta;
			TextMeshProUGUI obj = statusTextMesh;
			GenerationStatus status = dungeon.Generator.Status;
			((TMP_Text)obj).text = ((object)(GenerationStatus)(ref status)).ToString();
			if (!DevDebugOpen.IsSinglePlayerInShip())
			{
				CloseDevDebug();
			}
			if (Mouse.current.middleButton.isPressed)
			{
				Vector2 value = System.Runtime.CompilerServices.Unsafe.Read<Vector2>((void*)((InputControl<Vector2>)(object)((Pointer)Mouse.current).delta).value);
				Vector2 val = value;
				Transform transform = devCamera.transform;
				transform.position += new Vector3(0f - val.x, 0f, 0f - val.y);
			}
			float y = ((Vector2)((InputControl<Vector2>)(object)Mouse.current.scroll).value).y;
			if (y != 0f)
			{
				Vector3 position = devCamera.transform.position;
				position.y = Mathf.Clamp(position.y + y * -0.05f, cameraYRange.x, cameraYRange.y);
				devCamera.transform.position = position;
			}
		}

		public void OpenPanel(int index)
		{
			for (int i = 0; i < panels.Length; i++)
			{
				panels[i].SetPanelVisibility(i == index);
			}
		}

		public void ToggleCanvasExtended()
		{
			canvasExtended = !canvasExtended;
			canvasWidthTarget = (canvasExtended ? 800f : 440f);
		}

		public void SelectDungeonFlow(int index)
		{
			selectedExtendedDungeonFlow = dungeonFlows[index];
			selectedDungeonFlow = selectedExtendedDungeonFlow.DungeonFlow;
			dungeon.Generator.DungeonFlow = selectedDungeonFlow;
			if (!cacheDictionary.TryGetValue(selectedDungeonFlow, out var value))
			{
				DunGenExtender dunGenExtender = API.GetDunGenExtender(selectedDungeonFlow);
				value = new DungeonFlowCacheAssets(selectedDungeonFlow, dunGenExtender);
				cacheDictionary.Add(selectedDungeonFlow, value);
			}
			selectedAssetCache = value;
			UpdatePanels();
			Plugin.logger.LogInfo((object)("Selecting " + selectedExtendedDungeonFlow.DungeonName));
		}

		public void GenerateDungeon()
		{
			DeleteDungeon();
			Plugin.logger.LogInfo((object)$"Generating dungeon: {dungeon.Generator.IsGenerating}");
			fakeRoundManager = disabledGameObject.AddComponent<RoundManager>();
			fakeRoundManager.dungeonGenerator = dungeon;
			selectedExtendedDungeonFlow.DungeonEvents.onBeforeDungeonGenerate?.Invoke(fakeRoundManager);
			DungeonManager.GlobalDungeonEvents?.onBeforeDungeonGenerate?.Invoke(fakeRoundManager);
			DunGenPlusGenerator.GenerateBranchBoostedPathsTime = 0f;
			DunGenPlusGenerator.GetTileResultTime = 0f;
			DunGenPlusGenerator.DoorwayPairTime = 0f;
			DunGenPlusGenerator.CalculateWeightTime = 0f;
			dungeon.Generate();
		}

		public void DeleteDungeon()
		{
			Plugin.logger.LogInfo((object)"Deleting dungeon");
			dungeon.Generator.Clear(true);
			dungeon.Generator.Cancel();
			dungeon.Generator.RestrictDungeonToBounds = false;
			if (Object.op_Implicit((Object)(object)fakeRoundManager))
			{
				Object.Destroy((Object)(object)fakeRoundManager);
			}
			ClearTransformChildren(dungeon.Root.transform);
		}

		public void ClearTransformChildren(Transform root)
		{
			int childCount = root.childCount;
			for (int num = childCount - 1; num >= 0; num--)
			{
				Object.Destroy((Object)(object)((Component)root.GetChild(num)).gameObject);
			}
		}

		public void CloseDevDebug()
		{
			DeleteDungeon();
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}

		public void OnDungeonFinished(DungeonGenerator generator, GenerationStatus status)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Invalid comparison between Unknown and I4
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("Initial seed: " + MainPanel.Instance.seedInputField.inputField.text);
			stringBuilder.AppendLine($"Last seed: {generator.ChosenSeed}");
			if ((int)status == 6)
			{
				stringBuilder.AppendLine($"Tiles: {generator.CurrentDungeon.AllTiles.Count}");
				stringBuilder.AppendLine($"Main Tiles: {generator.CurrentDungeon.MainPathTiles.Count}");
				stringBuilder.AppendLine($"Branch Tiles: {generator.CurrentDungeon.BranchPathTiles.Count}");
				stringBuilder.AppendLine($"Doors: {generator.CurrentDungeon.Doors.Count}");
			}
			else if ((int)status == 7)
			{
				stringBuilder.AppendLine("<color=red>Failed</color>");
			}
			stringBuilder.AppendLine();
			GenerationStats generationStats = generator.GenerationStats;
			stringBuilder.AppendLine("<u>DunGen</u>");
			stringBuilder.AppendLine($"Retrys: {generationStats.TotalRetries}");
			stringBuilder.AppendLine($"Pre Process Time: {generationStats.PreProcessTime:F2} ms");
			stringBuilder.AppendLine($"Main Path Time: {generationStats.MainPathGenerationTime:F2} ms");
			stringBuilder.AppendLine($"Branch Path Time: {generationStats.BranchPathGenerationTime:F2} ms");
			stringBuilder.AppendLine($"Post Process Time: {generationStats.PostProcessTime:F2} ms");
			stringBuilder.AppendLine($"Total Time: {generationStats.TotalTime:F2} ms");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine($"GenerateBranch Time: {DunGenPlusGenerator.GenerateBranchBoostedPathsTime:F2} ms");
			stringBuilder.AppendLine($"GetTileResult Time: {DunGenPlusGenerator.GetTileResultTime:F2} ms");
			stringBuilder.AppendLine($"DoorwayPair Time: {DunGenPlusGenerator.DoorwayPairTime:F2} ms");
			stringBuilder.AppendLine($"CalculateWeight Time: {DunGenPlusGenerator.CalculateWeightTime:F2} ms");
			((TMP_Text)statsTextMesh).text = stringBuilder.ToString();
		}

		public void RecordNewSeed(int seed)
		{
			MainPanel.Instance?.seedInputField.Set(seed);
		}

		private void UpdatePanels()
		{
			DunFlowPanel.Instance?.UpdatePanel(refreshPanel: true);
			DunGenPlusPanel.Instance?.UpdatePanel(refreshPanel: true);
			AssetsPanel.Instance?.UpdatePanel(refreshPanel: true);
		}

		public void UpdateDungeonBounds()
		{
			DunGenPlusPanel.Instance?.UpdateDungeonBoundsHelper();
		}

		private void GetAllDungeonFlows()
		{
			dungeonFlows = PatchedContent.ExtendedDungeonFlows.ToArray();
			dungeonFlowSelectionDropDown.options = ((IEnumerable<ExtendedDungeonFlow>)dungeonFlows).Select((Func<ExtendedDungeonFlow, OptionData>)((ExtendedDungeonFlow d) => new OptionData(d.DungeonName))).ToList();
			SelectDungeonFlow(0);
		}

		private void CacheMainCamera()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			if (Object.op_Implicit((Object)(object)main))
			{
				lastMainCamera = main;
				lastCameraPosition = ((Component)main).transform.position;
				lastCameraRotation = ((Component)main).transform.rotation;
			}
		}

		private void BeginDevCamera()
		{
			Camera obj = lastMainCamera;
			if (obj != null)
			{
				((Component)obj).gameObject.SetActive(false);
			}
			devCamera.SetActive(true);
		}

		private void EndDevCamera()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			devCamera.SetActive(false);
			if (Object.op_Implicit((Object)(object)lastMainCamera))
			{
				((Component)lastMainCamera).transform.position = lastCameraPosition;
				((Component)lastMainCamera).transform.rotation = lastCameraRotation;
				((Component)lastMainCamera).gameObject.SetActive(true);
			}
		}

		public TextUIElement CreateHeaderUIField(Transform parentTransform, TitleParameter titleParameter)
		{
			GameObject val = Object.Instantiate<GameObject>(headerUIPrefab, parentTransform);
			TextUIElement component = val.GetComponent<TextUIElement>();
			component.SetupBase(titleParameter);
			return component;
		}

		public TextUIElement CreateTextUIField(Transform parentTransform, TitleParameter titleParameter)
		{
			GameObject val = Object.Instantiate<GameObject>(textUIPrefab, parentTransform);
			TextUIElement component = val.GetComponent<TextUIElement>();
			component.SetupBase(titleParameter);
			return component;
		}

		public void CreateSpaceUIField(Transform parentTransform)
		{
			Object.Instantiate<GameObject>(spaceUIPrefab, parentTransform);
		}

		public Transform CreateVerticalLayoutUIField(Transform parentTransform)
		{
			return Object.Instantiate<GameObject>(verticalLayoutUIPrefab, parentTransform).transform;
		}

		public IntInputField CreateIntInputField(Transform parentTransform, TitleParameter titleParameter, IntParameter intParameter, Action<int> setAction)
		{
			GameObject val = Object.Instantiate<GameObject>(intInputFieldPrefab, parentTransform);
			IntInputField component = val.GetComponent<IntInputField>();
			component.SetupInputField(titleParameter, intParameter, setAction);
			return component;
		}

		public FloatInputField CreateFloatInputField(Transform parentTransform, TitleParameter titleParameter, FloatParameter floatParameter, Action<float> setAction)
		{
			GameObject val = Object.Instantiate<GameObject>(floatInputFieldPrefab, parentTransform);
			FloatInputField component = val.GetComponent<FloatInputField>();
			component.SetupInputField(titleParameter, floatParameter, setAction);
			return component;
		}

		public BoolInputField CreateBoolInputField(Transform parentTransform, TitleParameter titleParameter, bool baseValue, Action<bool> setAction)
		{
			GameObject val = Object.Instantiate<GameObject>(boolInputFieldPrefab, parentTransform);
			BoolInputField component = val.GetComponent<BoolInputField>();
			component.SetupInputField(titleParameter, baseValue, setAction);
			return component;
		}

		public StringInputField CreateStringInputField(Transform parentTransform, TitleParameter titleParameter, string baseValue, Action<string> setAction)
		{
			GameObject val = Object.Instantiate<GameObject>(stringInputFieldPrefab, parentTransform);
			StringInputField component = val.GetComponent<StringInputField>();
			component.SetupInputField(titleParameter, baseValue, setAction);
			return component;
		}

		public Vector3InputField CreateVector3InputField(Transform parentTransform, TitleParameter titleParameter, Vector3 baseValue, Action<Vector3> setAction)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(vector3InputFieldPrefab, parentTransform);
			Vector3InputField component = val.GetComponent<Vector3InputField>();
			component.SetupInputField(titleParameter, baseValue, setAction);
			return component;
		}

		public IntRangeInputField CreateIntRangeInputField(Transform parentTransform, TitleParameter titleParameter, IntRange baseValue, Action<IntRange> setAction)
		{
			GameObject val = Object.Instantiate<GameObject>(intRangeInputFieldPrefab, parentTransform);
			IntRangeInputField component = val.GetComponent<IntRangeInputField>();
			component.SetupInputField(titleParameter, baseValue, setAction);
			return component;
		}

		public FloatRangeInputField CreateFloatRangeInputField(Transform parentTransform, TitleParameter titleParameter, FloatRange baseValue, Action<FloatRange> setAction)
		{
			GameObject val = Object.Instantiate<GameObject>(floatRangeInputFieldPrefab, parentTransform);
			FloatRangeInputField component = val.GetComponent<FloatRangeInputField>();
			component.SetupInputField(titleParameter, baseValue, setAction);
			return component;
		}

		public IntSliderField CreateIntSliderField(Transform parentTransform, TitleParameter titleParameter, IntParameter intParameter, Action<int> setAction)
		{
			GameObject val = Object.Instantiate<GameObject>(intSliderFieldPrefab, parentTransform);
			IntSliderField component = val.GetComponent<IntSliderField>();
			component.SetupInputField(titleParameter, intParameter, setAction);
			return component;
		}

		public ListUIElement CreateListUIField<T>(Transform parentTransform, TitleParameter titleParameter, List<T> list, bool useAddRemove = true)
		{
			return CreateListSimpleUIField(parentTransform, titleParameter, list, useExtended: false, useAddRemove);
		}

		public ListUIElement CreateListExtendedUIField<T>(Transform parentTransform, TitleParameter titleParameter, List<T> list, bool useAddRemove = true)
		{
			return CreateListSimpleUIField(parentTransform, titleParameter, list, useExtended: true, useAddRemove);
		}

		private ListUIElement CreateListSimpleUIField<T>(Transform parentTransform, TitleParameter titleParameter, List<T> list, bool useExtended, bool useAddRemove)
		{
			GameObject val = Object.Instantiate<GameObject>(listUIPrefab, parentTransform);
			ListUIElement component = val.GetComponent<ListUIElement>();
			component.SetupList(titleParameter, list, useExtended, useAddRemove);
			return component;
		}

		public DropdownInputField CreateOptionsUIField<T>(Transform parentTransform, TitleParameter titleParameter, int baseValue, Action<T> setAction, Func<int, T> convertIndex, IEnumerable<string> options)
		{
			GameObject val = Object.Instantiate<GameObject>(optionsUIPrefab, parentTransform);
			DropdownInputField component = val.GetComponent<DropdownInputField>();
			component.SetupDropdown(titleParameter, baseValue, setAction, convertIndex, options);
			return component;
		}

		public DropdownInputField CreateLevelOptionsUIField(Transform parentTransform, TitleParameter titleParameter, int baseValue, Action<ExtendedLevel> setAction)
		{
			MainPanel mainPanel = MainPanel.Instance;
			return CreateOptionsUIField(parentTransform, titleParameter, baseValue, setAction, (int i) => mainPanel.levels[i], mainPanel.levelOptions);
		}

		public DropdownInputField CreateMainPathExtenderUIField(Transform parentTransform, TitleParameter titleParameter, int baseValue, Action<MainPathExtender> setAction)
		{
			DungeonFlowCacheAssets assetCache = Instance.selectedAssetCache;
			return CreateOptionsUIField(parentTransform, titleParameter, baseValue, setAction, (int i) => assetCache.mainPathExtenders.list[i].Item, assetCache.mainPathExtenders.options);
		}

		public DropdownInputField CreateTileOptionsUIField(Transform parentTransform, TitleParameter titleParameter, int baseValue, Action<GameObject> setAction)
		{
			DungeonFlowCacheAssets assetCache = Instance.selectedAssetCache;
			return CreateOptionsUIField(parentTransform, titleParameter, baseValue, setAction, (int i) => assetCache.tiles.list[i].Item, assetCache.tiles.options);
		}

		public DropdownInputField CreateTileSetsOptionsUIField(Transform parentTransform, TitleParameter titleParameter, int baseValue, Action<TileSet> setAction)
		{
			DungeonFlowCacheAssets assetCache = Instance.selectedAssetCache;
			return CreateOptionsUIField(parentTransform, titleParameter, baseValue, setAction, (int i) => assetCache.tileSets.list[i].Item, assetCache.tileSets.options);
		}

		public DropdownInputField CreateArchetypeOptionsUIField(Transform parentTransform, TitleParameter titleParameter, int baseValue, Action<DungeonArchetype> setAction)
		{
			DungeonFlowCacheAssets assetCache = Instance.selectedAssetCache;
			return CreateOptionsUIField(parentTransform, titleParameter, baseValue, setAction, (int i) => assetCache.archetypes.list[i].Item, assetCache.archetypes.options);
		}

		public DropdownInputField CreateEnumOptionsUIField<T>(Transform parentTransform, TitleParameter titleParameter, int baseValue, Action<T> setAction) where T : Enum
		{
			string[] names = Enum.GetNames(typeof(T));
			return CreateOptionsUIField(parentTransform, titleParameter, baseValue, setAction, (int i) => (T)Enum.ToObject(typeof(T), i), names);
		}

		public DropdownInputField CreateAnimationCurveOptionsUIField(Transform parentTransform, TitleParameter titleParameter, AnimationCurve baseValue, Action<AnimationCurve> setAction)
		{
			var (curves, options) = CreateAnimationCurves(baseValue);
			setAction(curves[0]);
			return CreateOptionsUIField(parentTransform, titleParameter, 0, setAction, (int i) => curves[i], options);
		}

		private (List<AnimationCurve> animationCurves, List<string> options) CreateAnimationCurves(AnimationCurve custom)
		{
			List<AnimationCurve> list = new List<AnimationCurve>();
			List<string> list2 = new List<string>();
			if (custom != null)
			{
				list.Add(custom);
				list2.Add("Custom");
			}
			list.Add(AnimationCurve.Constant(0f, 1f, 1f));
			list2.Add("Constant 1");
			list.Add(AnimationCurve.Linear(0f, 0f, 1f, 1f));
			list2.Add("Linear 0-1");
			list.Add(AnimationCurve.Linear(1f, 1f, 0f, 0f));
			list2.Add("Linear 1-0");
			list.Add(AnimationCurve.EaseInOut(0f, 0f, 1f, 1f));
			list2.Add("EaseInOut 0-1");
			list.Add(AnimationCurve.EaseInOut(1f, 1f, 0f, 0f));
			list2.Add("EaseInOut 1-0");
			return (list, list2);
		}
	}
	internal class DevDebugOpen : MonoBehaviour
	{
		public static bool IsSinglePlayerInShip()
		{
			StartOfRound instance = StartOfRound.Instance;
			RoundManager instance2 = RoundManager.Instance;
			if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance2))
			{
				return instance.connectedPlayersAmount == 0 && instance.inShipPhase;
			}
			return false;
		}

		public void Update()
		{
			if (IfKeyPress(Keyboard.current.mKey, Keyboard.current.leftAltKey) && (Object)(object)DevDebugManager.Instance == (Object)null && IsSinglePlayerInShip())
			{
				Object.Instantiate<GameObject>(Assets.DevDebugPrefab);
			}
		}

		private bool IfKeyPress(KeyControl key, KeyControl hold)
		{
			if (((ButtonControl)hold).isPressed && ((ButtonControl)key).wasPressedThisFrame)
			{
				return true;
			}
			return false;
		}
	}
	internal class PanelTab : MonoBehaviour
	{
		public bool active;

		[Header("References")]
		public RectTransform rectTransform;

		public Image image;

		private void Update()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			float num = (active ? 48f : 36f);
			Color val = (active ? new Color(20f / 51f, 20f / 51f, 20f / 51f, 1f) : new Color(10f / 51f, 10f / 51f, 10f / 51f, 1f));
			Vector2 sizeDelta = rectTransform.sizeDelta;
			sizeDelta.y = Mathf.Lerp(sizeDelta.y, num, Time.deltaTime * 10f);
			rectTransform.sizeDelta = sizeDelta;
			Color color = ((Graphic)image).color;
			color = Color.Lerp(color, val, Time.deltaTime * 10f);
			((Graphic)image).color = color;
		}
	}
}
namespace DunGenPlus.DevTools.UIElements
{
	internal abstract class BaseInputField<T> : BaseUIElement
	{
		public abstract void Set(T value);

		protected int ParseTextInt(string text, int defaultValue = 0)
		{
			if (int.TryParse(te