Decompiled source of DungeonGenerationPlus v1.3.3

DunGenPlus.dll

Decompiled 3 days 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 bool IsDunGenExtenderActive(DungeonFlow dungeonFlow)
		{
			return IsDunGenExtenderActive(GetDunGenExtender(dungeonFlow));
		}

		public static bool IsDunGenExtenderActive(DunGenExtender extender)
		{
			return (Object)(object)extender != (Object)null && (Object)(object)extender == (Object)(object)DunGenPlusGenerator.Instance;
		}

		public static DunGenExtender CreateDunGenExtender(DungeonFlow dungeonFlow)
		{
			DunGenExtender dunGenExtender = ScriptableObject.CreateInstance<DunGenExtender>();
			dunGenExtender.DungeonFlow = dungeonFlow;
			return dunGenExtender;
		}

		public static void AddTileToMainPathDictionary(Dictionary<TileProxy, Tile> dictionary)
		{
			DunGenPlusGenerator.AddTileToMainPathDictionary(dictionary);
		}

		public static bool IsDevDebugModeActive()
		{
			return DevDebugManager.IsActive;
		}
	}
	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
	{
		internal const string LocalMainPathGlobalPropsTooltip = "Limits the amount of Global Props that can spawn on a single main path.\n\nThis does not afffect the global limit defined in DungeonFlow.";

		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>());

		[Tooltip("Limits the amount of Global Props that can spawn on a single main path.\n\nThis does not afffect the global limit defined in DungeonFlow.")]
		public List<LocalGlobalPropSettings> LocalGroupProps = new List<LocalGlobalPropSettings>();

		[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.3.3")]
	[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.3.3";

		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();
			DoorwayManager.onMainEntranceTeleportSpawnedEvent.AddEvent("DoorwayCleanup", DoorwayManager.onMainEntranceTeleportSpawnedFunction);
		}
	}
}
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)
			{
				PrintInstruction(instruction);
			}
		}

		public static void PrintInstruction(CodeInstruction inst)
		{
			string text = inst.opcode.ToString();
			string text2 = ((inst.operand != null) ? inst.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 TileProxy lastAttachTo;

		public static IEnumerable<TileSet> lastUseableTileSets;

		public static float lastNormalizedDepth;

		public static DungeonArchetype lastArchetype;

		[HarmonyPriority(800)]
		[HarmonyPatch(typeof(DungeonGenerator), "Generate")]
		[HarmonyPrefix]
		public static void GeneratePatch(ref DungeonGenerator __instance)
		{
			DunGenPlusGenerator.Deactivate();
			DungeonFlow dungeonFlow = __instance.DungeonFlow;
			DunGenExtender dunGenExtender = API.GetDunGenExtender(dungeonFlow);
			if (Object.op_Implicit((Object)(object)dunGenExtender) && dunGenExtender.Active)
			{
				Plugin.logger.LogInfo((object)("Loading DunGenExtender for " + ((Object)dungeonFlow).name));
				DunGenPlusGenerator.Activate(__instance, dunGenExtender);
			}
			else
			{
				Plugin.logger.LogInfo((object)"Did not load a DunGenExtenderer");
				DunGenPlusGenerator.Deactivate();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(DungeonGenerator), "InnerGenerate")]
		public static void InnerGeneratePatch(ref DungeonGenerator __instance, bool isRetry, ref IEnumerator __result)
		{
			if (API.IsDevDebugModeActive() && !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);
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(DungeonGenerator), "AddTile")]
		public static IEnumerable<CodeInstruction> AddTileDebugPatch(IEnumerable<CodeInstruction> instructions)
		{
			InstructionSequenceStandard addTileSequence = new InstructionSequenceStandard("Add Tile Placement");
			addTileSequence.AddBasic(OpCodes.Callvirt);
			addTileSequence.AddBasic(OpCodes.Ldc_I4_0);
			addTileSequence.AddBasic(OpCodes.Bgt);
			addTileSequence.AddBasicLocal(OpCodes.Ldloc_S, 9);
			foreach (CodeInstruction instruction in instructions)
			{
				if (addTileSequence.VerifyStage(instruction))
				{
					MethodInfo specialFunction = typeof(DunGenPlusGenerator).GetMethod("RecordLastTilePlacementResult", BindingFlags.Static | BindingFlags.Public);
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Ldloc_S, (object)9);
					yield return new CodeInstruction(OpCodes.Call, (object)specialFunction);
					yield return instruction;
				}
				else
				{
					yield return instruction;
				}
			}
			addTileSequence.ReportComplete();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(Dungeon), "FromProxy")]
		public static IEnumerable<CodeInstruction> FromProxyPatch(IEnumerable<CodeInstruction> instructions)
		{
			InstructionSequenceStandard endSequence = new InstructionSequenceStandard("Forloop End");
			endSequence.AddBasicLocal(OpCodes.Ldloca_S, 1);
			endSequence.AddBasic(OpCodes.Constrained);
			endSequence.AddBasic(OpCodes.Callvirt);
			endSequence.AddBasic(OpCodes.Endfinally);
			foreach (CodeInstruction instruction in instructions)
			{
				if (endSequence.VerifyStage(instruction))
				{
					MethodInfo specialFunction = typeof(DunGenPlusGenerator).GetMethod("AddTileToMainPathDictionary", BindingFlags.Static | BindingFlags.Public);
					yield return new CodeInstruction(OpCodes.Ldloc_0, (object)null);
					yield return new CodeInstruction(OpCodes.Call, (object)specialFunction);
				}
				yield return instruction;
			}
			endSequence.ReportComplete();
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(DungeonGenerator), "ProcessGlobalProps")]
		public static bool ProcessGlobalPropsPatch(ref DungeonGenerator __instance)
		{
			if (DunGenPlusGenerator.Active && DunGenPlusGenerator.Properties.MainPathProperties.MainPathDetails.Any((MainPathExtender d) => d.LocalGroupProps.Count > 0))
			{
				Plugin.logger.LogDebug((object)"Performing Local Global Props algorithm");
				DunGenPlusGenerator.ProcessGlobalPropsPerMainPath(__instance);
				return false;
			}
			return true;
		}

		[HarmonyTranspiler]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		public static IEnumerable<CodeInstruction> GenerateMainPathDebugPatch(IEnumerable<CodeInstruction> instructions)
		{
			InstructionSequenceStandard tileProxyNullSequence = new InstructionSequenceStandard("TileProxyNull");
			tileProxyNullSequence.AddBasic(OpCodes.Br);
			tileProxyNullSequence.AddBasicLocal(OpCodes.Ldloc_S, 14);
			tileProxyNullSequence.AddBasic(OpCodes.Brtrue);
			foreach (CodeInstruction instruction in instructions)
			{
				if (tileProxyNullSequence.VerifyStage(instruction))
				{
					MethodInfo specialFunction = typeof(DunGenPlusGenerator).GetMethod("PrintAddTileErrorQuick", BindingFlags.Static | BindingFlags.Public);
					FieldInfo field = typeof(DungeonGenerator).Assembly.GetType("DunGen.DungeonGenerator+<GenerateMainPath>d__100").GetField("<j>5__8", BindingFlags.Instance | BindingFlags.NonPublic);
					yield return instruction;
					yield return new CodeInstruction(OpCodes.Ldloc_1, (object)null);
					yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					yield return new CodeInstruction(OpCodes.Ldfld, (object)field);
					yield return new CodeInstruction(OpCodes.Call, (object)specialFunction);
				}
				else
				{
					yield return instruction;
				}
			}
			tileProxyNullSequence.ReportComplete();
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(DungeonGenerator), "AddTile")]
		public static void AddTileDebugPatch(TileProxy attachTo, IEnumerable<TileSet> useableTileSets, float normalizedDepth, DungeonArchetype archetype)
		{
			lastAttachTo = attachTo;
			lastUseableTileSets = useableTileSets;
			lastNormalizedDepth = normalizedDepth;
			lastArchetype = archetype;
		}
	}
	internal class LethalLevelLoaderPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(Patches), "DungeonGeneratorGenerate_Prefix")]
		public static bool DungeonGeneratorGenerate_Prefix_Patches_Prefix()
		{
			return (Object)(object)DevDebugManager.Instance == (Object)null;
		}

		[HarmonyPatch(typeof(EventPatches), "DungeonGeneratorGenerate_Prefix")]
		[HarmonyPrefix]
		public static void DungeonGeneratorGenerate_Prefix_EventPatches_Prefix()
		{
			ScrapItemManager.Initialize(Patches.RoundManager);
			EnemyManager.Initialize(Patches.RoundManager);
		}
	}
	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) });
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(RoundManager), "Start")]
		public static void StartPatch(ref RoundManager __instance)
		{
			ScrapItemManager.UndoPreviousChanges();
			EnemyManager.UndoPreviousChanges();
		}

		[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
	{
	}
}
namespace DunGenPlus.Managers
{
	public static class EnemyManager
	{
		internal static SelectableLevel previousLevel;

		internal static List<SpawnableEnemyWithRarity> previouslyAddedEnemies = new List<SpawnableEnemyWithRarity>();

		internal static List<SpawnableEnemyWithRarity> previouslyModifiedEnemies = new List<SpawnableEnemyWithRarity>();

		internal static void UndoPreviousChanges()
		{
			if (!((Object)(object)previousLevel != (Object)null))
			{
				return;
			}
			Plugin.logger.LogDebug((object)("Undoing changes of EnemyManager for " + previousLevel.PlanetName));
			List<SpawnableEnemyWithRarity> enemies = previousLevel.Enemies;
			if (previouslyAddedEnemies.Count > 0)
			{
				for (int num = previouslyAddedEnemies.Count - 1; num >= 0; num--)
				{
					SpawnableEnemyWithRarity val = previouslyAddedEnemies[num];
					int num2 = enemies.Count - 1;
					while (true)
					{
						if (num2 >= 0)
						{
							SpawnableEnemyWithRarity val2 = enemies[num2];
							if (val2 == val)
							{
								enemies.RemoveAt(num2);
								Plugin.logger.LogDebug((object)("Properly removed temporary enemy " + val.enemyType.enemyName));
								break;
							}
							num2--;
							continue;
						}
						Plugin.logger.LogWarning((object)("Couldn't find/remove temporary enemy " + val.enemyType.enemyName));
						break;
					}
				}
				previouslyAddedEnemies.Clear();
			}
			if (previouslyModifiedEnemies.Count > 0)
			{
				for (int i = 0; i < previouslyModifiedEnemies.Count; i++)
				{
					SpawnableEnemyWithRarity val3 = previouslyModifiedEnemies[i];
					int num3 = 0;
					while (true)
					{
						if (num3 < enemies.Count)
						{
							if ((Object)(object)enemies[num3].enemyType == (Object)(object)val3.enemyType)
							{
								enemies[num3] = val3;
								Plugin.logger.LogDebug((object)("Properly fixed modified enemy " + val3.enemyType.enemyName));
								break;
							}
							num3++;
							continue;
						}
						Plugin.logger.LogWarning((object)("Couldn't find/fix modified enemy " + val3.enemyType.enemyName));
						break;
					}
				}
				previouslyModifiedEnemies.Clear();
			}
			previousLevel = null;
		}

		internal static void Initialize(RoundManager roundManager)
		{
			UndoPreviousChanges();
			previousLevel = roundManager.currentLevel;
			Plugin.logger.LogDebug((object)("Initialized EnemyManager to " + previousLevel.PlanetName));
		}

		public static void AddEnemies(IEnumerable<SpawnableEnemyWithRarity> newEnemies)
		{
			foreach (SpawnableEnemyWithRarity newEnemy in newEnemies)
			{
				AddEnemy(newEnemy);
			}
		}

		public static void AddEnemy(SpawnableEnemyWithRarity newEnemy)
		{
			List<SpawnableEnemyWithRarity> enemies = previousLevel.Enemies;
			for (int i = 0; i < enemies.Count; i++)
			{
				if ((Object)(object)enemies[i].enemyType == (Object)(object)newEnemy.enemyType)
				{
					if (enemies[i].rarity == newEnemy.rarity)
					{
						Plugin.logger.LogDebug((object)("Skipping " + newEnemy.enemyType.enemyName + " as it has the same rarity"));
						return;
					}
					previouslyModifiedEnemies.Add(enemies[i]);
					enemies[i] = newEnemy;
					Plugin.logger.LogDebug((object)$"Modifying already existing enemy {newEnemy.enemyType.enemyName} to new weight {newEnemy.rarity}");
					return;
				}
			}
			previouslyAddedEnemies.Add(newEnemy);
			enemies.Add(newEnemy);
			Plugin.logger.LogDebug((object)$"Adding temporary enemy {newEnemy.enemyType.enemyName} with weight {newEnemy.rarity}");
		}
	}
	public static class ScrapItemManager
	{
		internal static SelectableLevel previousLevel;

		internal static List<SpawnableItemWithRarity> previouslyAddedItems = new List<SpawnableItemWithRarity>();

		internal static List<SpawnableItemWithRarity> previouslyModifiedItems = new List<SpawnableItemWithRarity>();

		internal static void UndoPreviousChanges()
		{
			if (!((Object)(object)previousLevel != (Object)null))
			{
				return;
			}
			Plugin.logger.LogDebug((object)("Undoing changes of ScrapItemManager for " + previousLevel.PlanetName));
			List<SpawnableItemWithRarity> spawnableScrap = previousLevel.spawnableScrap;
			if (previouslyAddedItems.Count > 0)
			{
				for (int num = previouslyAddedItems.Count - 1; num >= 0; num--)
				{
					SpawnableItemWithRarity val = previouslyAddedItems[num];
					int num2 = spawnableScrap.Count - 1;
					while (true)
					{
						if (num2 >= 0)
						{
							SpawnableItemWithRarity val2 = spawnableScrap[num2];
							if (val2 == val)
							{
								spawnableScrap.RemoveAt(num2);
								Plugin.logger.LogDebug((object)("Properly removed temporary item " + val.spawnableItem.itemName));
								break;
							}
							num2--;
							continue;
						}
						Plugin.logger.LogWarning((object)("Couldn't find/remove temporary item " + val.spawnableItem.itemName));
						break;
					}
				}
				previouslyAddedItems.Clear();
			}
			if (previouslyModifiedItems.Count > 0)
			{
				for (int i = 0; i < previouslyModifiedItems.Count; i++)
				{
					SpawnableItemWithRarity val3 = previouslyModifiedItems[i];
					int num3 = 0;
					while (true)
					{
						if (num3 < spawnableScrap.Count)
						{
							if ((Object)(object)spawnableScrap[num3].spawnableItem == (Object)(object)val3.spawnableItem)
							{
								spawnableScrap[num3] = val3;
								Plugin.logger.LogDebug((object)("Properly fixed modified item " + val3.spawnableItem.itemName));
								break;
							}
							num3++;
							continue;
						}
						Plugin.logger.LogWarning((object)("Couldn't find/fix modified item " + val3.spawnableItem.itemName));
						break;
					}
				}
				previouslyModifiedItems.Clear();
			}
			previousLevel = null;
		}

		internal static void Initialize(RoundManager roundManager)
		{
			UndoPreviousChanges();
			previousLevel = roundManager.currentLevel;
			Plugin.logger.LogDebug((object)("Initialized ScrapItemManager to " + previousLevel.PlanetName));
		}

		public static void AddItems(IEnumerable<SpawnableItemWithRarity> newItems)
		{
			foreach (SpawnableItemWithRarity newItem in newItems)
			{
				AddItem(newItem);
			}
		}

		public static void AddItem(SpawnableItemWithRarity newItem)
		{
			List<SpawnableItemWithRarity> spawnableScrap = previousLevel.spawnableScrap;
			for (int i = 0; i < spawnableScrap.Count; i++)
			{
				if ((Object)(object)spawnableScrap[i].spawnableItem == (Object)(object)newItem.spawnableItem)
				{
					if (spawnableScrap[i].rarity == newItem.rarity)
					{
						Plugin.logger.LogDebug((object)("Skipping " + newItem.spawnableItem.itemName + " as it has the same rarity"));
						return;
					}
					previouslyModifiedItems.Add(spawnableScrap[i]);
					spawnableScrap[i] = newItem;
					Plugin.logger.LogDebug((object)$"Modifying already existing item {newItem.spawnableItem.itemName} to new weight {newItem.rarity}");
					return;
				}
			}
			previouslyAddedItems.Add(newItem);
			spawnableScrap.Add(newItem);
			Plugin.logger.LogDebug((object)$"Adding temporary item {newItem.spawnableItem.itemName} with weight {newItem.rarity}");
		}
	}
	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();
			}
			if (doorwayCleanupList.Count != 0)
			{
				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;

		public static TilePlacementResult lastTilePlacementResult;

		internal static HDRenderPipelineAsset previousHDRPAsset;

		internal static HDRenderPipelineAsset newHDRPAsset;

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

		private static Dictionary<Tile, int> tileMainPath = new Dictionary<Tile, 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 PrintAddTileError(DungeonGenerator gen, TileProxy previousTile, DungeonArchetype archetype, IEnumerable<TileSet> useableTileSets, int branchId, int lineLength, float lineRatio)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			string text = ((previousTile != null) ? ((Object)previousTile.Prefab).name : "NULL");
			string text2 = (Object.op_Implicit((Object)(object)archetype) ? ((Object)archetype).name : "NULL");
			string text3 = string.Join(", ", useableTileSets);
			List<string> list = new List<string>();
			list.Add($"Main branch gen failed at Branch {branchId} (Length: {lineLength}, Ratio: {lineRatio})");
			list.Add("Prev tile: " + text);
			list.Add("Archetype: " + text2);
			list.Add("Tilesets: " + text3);
			list.Add($"Reason: {lastTilePlacementResult}");
			if (previousTile != null)
			{
				string text4 = string.Join(", ", previousTile.UnusedDoorways.Select((DoorwayProxy d) => ((Object)((Component)d.DoorwayComponent).gameObject).name));
				string text5 = string.Join(", ", previousTile.UsedDoorways.Select((DoorwayProxy d) => ((Object)((Component)d.DoorwayComponent).gameObject).name));
				list.Add("Available Doorways: " + text4);
				list.Add("Used Doorways: " + text5);
				if (API.IsDevDebugModeActive())
				{
					Queue<DoorwayPair> doorwayPairs = GetDoorwayPairs(gen, previousTile, useableTileSets, archetype, lineRatio);
					string text6 = string.Join(", ", from d in doorwayPairs.Select((DoorwayPair t) => ((DoorwayPair)(ref t)).NextTemplate.Prefab).Distinct()
						select ((Object)d).name);
					list.Add("Next Possible Tiles: " + text6);
				}
			}
			list.Add(string.Empty);
			Plugin.logger.LogDebug((object)string.Join("\n", list));
		}

		public static void PrintAddTileErrorQuick(DungeonGenerator gen, int lineLength)
		{
			PrintAddTileError(gen, DungeonGeneratorPatch.lastAttachTo, DungeonGeneratorPatch.lastArchetype, DungeonGeneratorPatch.lastUseableTileSets, 0, lineLength, DungeonGeneratorPatch.lastNormalizedDepth);
		}

		public static void RecordLastTilePlacementResult(DungeonGenerator gen, 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;
		}

		public static void ProcessGlobalPropsPerMainPath(DungeonGenerator dungeonGenerator)
		{
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Expected O, but got Unknown
			HashSet<int> hashSet = (from x in Properties.MainPathProperties.MainPathDetails.SelectMany((MainPathExtender d) => d.LocalGroupProps)
				select x.ID).ToHashSet();
			Dictionary<int, Dictionary<int, GameObjectChanceTable>> dictionary = new Dictionary<int, Dictionary<int, GameObjectChanceTable>>();
			Dictionary<int, GameObjectChanceTable> dictionary2 = new Dictionary<int, GameObjectChanceTable>();
			foreach (Tile allTile in dungeonGenerator.CurrentDungeon.AllTiles)
			{
				GlobalProp[] componentsInChildren = ((Component)allTile).GetComponentsInChildren<GlobalProp>();
				foreach (GlobalProp val in componentsInChildren)
				{
					GameObjectChanceTable value2;
					if (hashSet.Contains(val.PropGroupID))
					{
						if (!dictionary.TryGetValue(val.PropGroupID, out var value))
						{
							value = new Dictionary<int, GameObjectChanceTable>();
							dictionary.Add(val.PropGroupID, value);
						}
						int mainPathIndexFromTile = GetMainPathIndexFromTile(allTile);
						if (!value.TryGetValue(mainPathIndexFromTile, out value2))
						{
							value2 = new GameObjectChanceTable();
							value.Add(mainPathIndexFromTile, value2);
						}
					}
					else if (!dictionary2.TryGetValue(val.PropGroupID, out value2))
					{
						value2 = new GameObjectChanceTable();
						dictionary2.Add(val.PropGroupID, value2);
					}
					float num = (allTile.Placement.IsOnMainPath ? val.MainPathWeight : val.BranchPathWeight);
					num *= val.DepthWeightScale.Evaluate(allTile.Placement.NormalizedDepth);
					value2.Weights.Add(new GameObjectChance(((Component)val).gameObject, num, 0f, (TileSet)null));
				}
			}
			foreach (Dictionary<int, GameObjectChanceTable> value4 in dictionary.Values)
			{
				foreach (GameObjectChanceTable value5 in value4.Values)
				{
					foreach (GameObjectChance weight in value5.Weights)
					{
						weight.Value.SetActive(false);
					}
				}
			}
			foreach (GameObjectChanceTable value6 in dictionary2.Values)
			{
				foreach (GameObjectChance weight2 in value6.Weights)
				{
					weight2.Value.SetActive(false);
				}
			}
			List<int> list = new List<int>(dictionary.Count + dictionary2.Count);
			foreach (KeyValuePair<int, GameObjectChanceTable> pair in dictionary2)
			{
				if (list.Contains(pair.Key))
				{
					Plugin.logger.LogWarning((object)("Dungeon Flow contains multiple entries for the global prop group ID: " + pair.Key + ". Only the first entry will be used."));
					continue;
				}
				GlobalPropSettings val2 = dungeonGenerator.DungeonFlow.GlobalProps.Where((GlobalPropSettings x) => x.ID == pair.Key).FirstOrDefault();
				if (val2 != null)
				{
					GameObjectChanceTable table2 = pair.Value.Clone();
					int random = val2.Count.GetRandom(dungeonGenerator.RandomStream);
					int num2 = ProcessGlobalPropID(table2, random, 0, random);
					Plugin.logger.LogDebug((object)$"Global ID: {pair.Key} ({num2} / {random})");
					list.Add(pair.Key);
				}
			}
			foreach (KeyValuePair<int, Dictionary<int, GameObjectChanceTable>> item in dictionary)
			{
				int globalPropId = item.Key;
				if (list.Contains(globalPropId))
				{
					Plugin.logger.LogWarning((object)("Dungeon Flow contains multiple entries for the global prop group ID: " + item.Key + ". Only the first entry will be used."));
					continue;
				}
				GlobalPropSettings val3 = dungeonGenerator.DungeonFlow.GlobalProps.Where((GlobalPropSettings x) => x.ID == globalPropId).FirstOrDefault();
				if (val3 == null)
				{
					continue;
				}
				int num3 = 0;
				int random2 = val3.Count.GetRandom(dungeonGenerator.RandomStream);
				Dictionary<int, GameObjectChanceTable> value3 = item.Value;
				Plugin.logger.LogDebug((object)$"Local ID: {item.Key} (Max {random2})");
				List<int> list2 = new List<int>();
				foreach (KeyValuePair<int, GameObjectChanceTable> item2 in value3)
				{
					int key = item2.Key;
					List<LocalGlobalPropSettings> localGroupProps = Properties.MainPathProperties.GetMainPathDetails(key).LocalGroupProps;
					LocalGlobalPropSettings localGlobalPropSettings = localGroupProps.Where((LocalGlobalPropSettings x) => x.ID == globalPropId).FirstOrDefault();
					if (localGlobalPropSettings == null)
					{
						Plugin.logger.LogDebug((object)$"Main Path {key}: No local ID defined, skipping");
						continue;
					}
					GameObjectChanceTable table3 = item2.Value.Clone();
					int random3 = localGlobalPropSettings.Count.GetRandom(dungeonGenerator.RandomStream);
					int num4 = ProcessGlobalPropID(table3, random3, num3, random2);
					num3 += num4;
					Plugin.logger.LogDebug((object)$"Main Path {key}: Local ({num4} / {random3}), Global ({num3} / {random2})");
					if (!localGlobalPropSettings.UseToReachGlobalPropLimit)
					{
						list2.Add(key);
					}
				}
				foreach (int item3 in list2)
				{
					value3.Remove(item3);
				}
				if (num3 < random2 && value3.Count > 0)
				{
					string text = string.Join(", ", value3.Keys);
					Plugin.logger.LogDebug((object)("Combining main paths (" + text + ") into one GameObjectChanceTable"));
					GameObjectChanceTable[] tables2 = value3.Select((KeyValuePair<int, GameObjectChanceTable> d) => d.Value).ToArray();
					int num5 = ProcessRemainingGlobalPropID(tables2, random2 - num3);
					num3 += num5;
					Plugin.logger.LogDebug((object)$"Spawned remaining props ({num3} / {random2})");
				}
				list.Add(item.Key);
			}
			int ProcessGlobalPropID(GameObjectChanceTable table, int localMax, int globalCount, int globalMax)
			{
				localMax = Mathf.Clamp(localMax, 0, table.Weights.Count);
				int k;
				for (k = 0; k < localMax && k + globalCount < globalMax; k++)
				{
					GameObjectChance random4 = table.GetRandom(dungeonGenerator.RandomStream, true, 0f, (GameObject)null, true, true);
					if (random4 != null && (Object)(object)random4.Value != (Object)null)
					{
						random4.Value.SetActive(true);
					}
				}
				return k;
			}
			int ProcessRemainingGlobalPropID(GameObjectChanceTable[] tables, int count)
			{
				count = Mathf.Clamp(count, 0, tables.Sum((GameObjectChanceTable t) => t.Weights.Count));
				int j;
				for (j = 0; j < count; j++)
				{
					GameObject combinedRandom = GameObjectChanceTable.GetCombinedRandom(dungeonGenerator.RandomStream, true, 0f, tables);
					if ((Object)(object)combinedRandom != (Object)null)
					{
						combinedRandom.SetActive(true);
					}
				}
				return j;
			}
		}

		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];
		}

		public static int GetMainPathIndexFromTile(Tile tile)
		{
			if (tileMainPath.TryGetValue(tile, out var value))
			{
				return value;
			}
			Plugin.logger.LogWarning((object)"Error with GetMainPathIndexFromTile.\nPLEASE REPORT TO MR. DEV WITH YOUR MOD PACK. THIS SHOULD NOT BE HAPPENING!");
			return 0;
		}

		public static void AddTileProxy(TileProxy tileProxy, int index)
		{
			tileProxyMainPath.Add(tileProxy, index);
		}

		public static void AddMainPathTileProxies(IEnumerable<TileProxy> tileProxies, int index)
		{
			float num = tileProxies.Last().Placement.PathDepth;
			foreach (TileProxy tileProxy in tileProxies)
			{
				AddTileProxy(tileProxy, index);
				tileProxy.Placement.NormalizedPathDepth = (float)tileProxy.Placement.PathDepth / num;
			}
		}

		public static void BuildBranchPathTileProxiesDictionary(DungeonProxy dungeonProxy)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			int index = 0;
			foreach (ProxyDoorwayConnection connection in dungeonProxy.Connections)
			{
				ProxyDoorwayConnection current = connection;
				TileProxy tileProxy = ((ProxyDoorwayConnection)(ref current)).A.TileProxy;
				if (tileProxy.Placement.IsOnMainPath)
				{
					index = GetMainPathIndexFromTileProxy(tileProxy);
				}
				TileProxy tileProxy2 = ((ProxyDoorwayConnection)(ref current)).B.TileProxy;
				if (!tileProxy2.Placement.IsOnMainPath)
				{
					AddTileProxy(tileProxy2, index);
				}
			}
		}

		public static void AddTileToMainPathDictionary(Dictionary<TileProxy, Tile> dictionary)
		{
			if (!Active)
			{
				return;
			}
			foreach (KeyValuePair<TileProxy, Tile> item in dictionary)
			{
				tileMainPath.Add(item.Value, GetMainPathIndexFromTileProxy(item.Key));
			}
		}

		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();
			tileMainPath.Clear();
			List<TileProxy> firstMainPathTiles = gen.proxyDungeon.MainPathTiles.ToList();
			AddMainPathTileProxies(firstMainPathTiles, 0);
			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>> { firstMainPathTiles };
			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)
					{
						PrintAddTileError(gen, previousTile, archetype, useableTileSets, b + 1, t2, lineDepthRatio2);
						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;
				}
				AddMainPathTileProxies(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];
			if (!Properties.BranchPathMultiSimulationProperties.UseBranchPathMultiSim)
			{
				BuildBranchPathTileProxiesDictionary(gen.proxyDungeon);
			}
			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;
			BuildBranchPathTileProxiesDictionary(gen.proxyDungeon);
			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;
							AddMainPathTileProxies(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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Invalid comparison between Unknown and I4
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: 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));
			DoorwayPairStopwatch.Reset();
			DoorwayPairStopwatch.Start();
			Queue<DoorwayPair> doorwayPairs = GetDoorwayPairs(gen, attachTo, collection, archetype, normalizedDepth);
			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 Queue<DoorwayPair> GetDoorwayPairs(DungeonGenerator gen, TileProxy attachTo, IEnumerable<GameObjectChance> collection, DungeonArchetype archetype, float normalizedDepth)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_009c: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			bool value = attachTo.PrefabTile.AllowRotation;
			if (gen.OverrideAllowTileRotation)
			{
				value = gen.AllowTileRotation;
			}
			DoorwayPairFinder val = new DoorwayPairFinder();
			val.DungeonFlow = gen.DungeonFlow;
			val.RandomStream = gen.RandomStream;
			val.Archetype = archetype;
			val.GetTileTemplateDelegate = new GetTileTemplateDelegate(gen.GetTileTemplate);
			val.IsOnMainPath = false;
			val.NormalizedDepth = normalizedDepth;
			val.PreviousTile = attachTo;
			val.UpVector = gen.UpVector;
			val.AllowRotation = value;
			val.TileWeights = new List<GameObjectChance>(collection);
			val.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 val2 = (TileRepeatMode)0;
				if (gen.OverrideRepeatMode)
				{
					val2 = gen.RepeatMode;
				}
				else if (next != null)
				{
					val2 = next.PrefabTile.RepeatMode;
				}
				TileRepeatMode val3 = val2;
				TileRepeatMode val4 = val3;
				return (int)val4 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 {val2} is not implemented"), 
				};
			};
			int? num = (gen.UseMaximumPairingAttempts ? new int?(gen.MaxPairingAttempts) : null);
			return val.GetDoorwayPairs(num);
		}

		private static Queue<DoorwayPair> GetDoorwayPairs(DungeonGenerator gen, TileProxy attachTo, IEnumerable<TileSet> useableTileSets, DungeonArchetype archetype, float normalizedDepth)
		{
			IEnumerable<GameObjectChance> collection = useableTileSets.SelectMany((TileSet t) => t.TileWeights.Weights);
			return GetDoorwayPairs(gen, attachTo, collection, archetype, normalizedDepth);
		}

		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;
					}
					AddTileProxy(val, GetMainPathIndexFromTileProxy(item2));
					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 || API.IsDevDebugModeActive();
		}
	}
	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 LayoutElement canvasLayoutElement;

		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 bool canvasExtendedInAnimation;

		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;
			AssetsPanel.Instance = null;
			Cursor.lockState = (CursorLockMode)1;
			Cursor.visible = false;
			EndDevCamera();
		}

		private unsafe void Update()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or

LoadstoneNighty.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using DunGen;
using DunGen.Graph;
using DunGenPlus;
using DunGenPlus.Collections;
using HarmonyLib;
using Loadstone.Patches;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("LoadstoneNighty")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LoadstoneNighty")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b7c6eabd-16db-4de8-8013-1fa7da6e8de8")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace LoadstoneNighty;

public class PatchVer16
{
	public static void Activate()
	{
		try
		{
			Plugin.Instance.harmony.PatchAll(typeof(PatchVer16));
		}
		catch
		{
		}
		Plugin.logger.LogInfo((object)"FromProxyEnd function has been patched!");
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(FromProxyPatches), "FromProxyEnd")]
	public static void FromProxyEndPatch(Dictionary<TileProxy, Tile> dictionary)
	{
		API.AddTileToMainPathDictionary(dictionary);
	}
}
public class PatchVer17
{
	public static void Activate()
	{
		DungenOptimizationPatches.tileCollectors.Add(GetTiles);
		Plugin.logger.LogInfo((object)"DungenOptimizationPatches function has been patched!");
	}

	private static HashSet<Tile> GetTiles(DungeonGenerator generator)
	{
		DungeonFlow dungeonFlow = generator.DungeonFlow;
		DunGenExtender dunGenExtender = API.GetDunGenExtender(dungeonFlow);
		HashSet<Tile> tiles = new HashSet<Tile>();
		if (API.IsDunGenExtenderActive(dunGenExtender))
		{
			Plugin.logger.LogDebug((object)"Creating custom hashset for Loadstone");
			DunGenExtenderProperties properties = dunGenExtender.Properties;
			GenerateTileHashSet(ref tiles, properties.MainPathProperties.MainPathDetails);
			GenerateTileHashSet(ref tiles, properties.AdditionalTilesProperties.AdditionalTileSets);
			GenerateTileHashSet(ref tiles, properties.NormalNodeArchetypesProperties.NormalNodeArchetypes);
			GenerateTileHashSet(ref tiles, properties.LineRandomizerProperties.Archetypes);
		}
		return tiles;
	}

	private static void GenerateTileHashSet(ref HashSet<Tile> tiles, List<NodeArchetype> nodes)
	{
		foreach (NodeArchetype node in nodes)
		{
			GenerateTileHashSet(ref tiles, node.Archetypes);
		}
	}

	private static void GenerateTileHashSet(ref HashSet<Tile> tiles, List<AdditionalTileSetList> list)
	{
		foreach (AdditionalTileSetList item in list)
		{
			GenerateTileHashSet(ref tiles, item.TileSets);
		}
	}

	private static void GenerateTileHashSet(ref HashSet<Tile> tiles, List<MainPathExtender> extenders)
	{
		foreach (MainPathExtender extender in extenders)
		{
			GenerateTileHashSet(ref tiles, extender.Nodes.Value);
			GenerateTileHashSet(ref tiles, extender.Lines.Value);
		}
	}

	private static void GenerateTileHashSet(ref HashSet<Tile> tiles, List<GraphNode> nodes)
	{
		foreach (GraphNode node in nodes)
		{
			GenerateTileHashSet(ref tiles, node.TileSets);
		}
	}

	private static void GenerateTileHashSet(ref HashSet<Tile> tiles, List<GraphLine> lines)
	{
		foreach (GraphLine line in lines)
		{
			GenerateTileHashSet(ref tiles, line.DungeonArchetypes);
		}
	}

	private static void GenerateTileHashSet(ref HashSet<Tile> tiles, List<DungeonArchetype> archetypes)
	{
		foreach (DungeonArchetype archetype in archetypes)
		{
			GenerateTileHashSet(ref tiles, archetype.TileSets);
			GenerateTileHashSet(ref tiles, archetype.BranchCapTileSets);
		}
	}

	private static void GenerateTileHashSet(ref HashSet<Tile> tiles, List<TileSet> tileSets)
	{
		foreach (TileSet tileSet in tileSets)
		{
			foreach (GameObjectChance weight in tileSet.TileWeights.Weights)
			{
				Tile component = weight.Value.GetComponent<Tile>();
				if ((Object)(object)component != (Object)null)
				{
					tiles.Add(component);
				}
			}
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(FromProxyPatches), "FromProxyEnd")]
	public static void FromProxyEndPatch(Dictionary<TileProxy, Tile> dictionary)
	{
		API.AddTileToMainPathDictionary(dictionary);
	}
}
[BepInPlugin("dev.ladyalice.dungenplus.loadstonepatch", "Dungeon Generation Plus Loadstone Patch", "1.0.0")]
[BepInDependency("dev.ladyalice.dungenplus", "1.2.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	public const string modGUID = "dev.ladyalice.dungenplus.loadstonepatch";

	private const string modName = "Dungeon Generation Plus Loadstone Patch";

	private const string modVersion = "1.0.0";

	public const string targetModGUID = "com.adibtw.loadstone";

	public const string targetModVersion = "0.1.17";

	public readonly Harmony harmony = new Harmony("dev.ladyalice.dungenplus.loadstonepatch");

	public static Plugin Instance { get; private set; }

	public static ManualLogSource logger { get; internal set; }

	private void Awake()
	{
		if ((Object)(object)Instance == (Object)null)
		{
			Instance = this;
		}
		logger = Logger.CreateLogSource("dev.ladyalice.dungenplus.loadstonepatch");
		if (Chainloader.PluginInfos.ContainsKey("com.adibtw.loadstone"))
		{
			logger.LogInfo((object)"Plugin Dungeon Generation Plus Loadstone Patch has been added!");
			PatchVer16.Activate();
			PluginInfo val = Chainloader.PluginInfos["com.adibtw.loadstone"];
			Version version = val.Metadata.Version;
			bool flag;
			if (string.IsNullOrWhiteSpace("0.1.17"))
			{
				flag = true;
			}
			else
			{
				Version version2 = new Version("0.1.17");
				flag = version >= version2;
			}
			if (flag)
			{
				PatchVer17.Activate();
			}
		}
	}
}