Decompiled source of Rando v0.1.3

Silksong.Rando.dll

Decompiled 17 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Xml.Linq;
using BepInEx;
using BepInEx.Logging;
using GlobalEnums;
using GlobalSettings;
using HarmonyLib;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using Newtonsoft.Json;
using PrepatcherPlugin;
using QuestPlaymakerActions;
using Silksong.DataManager;
using Silksong.FsmUtil;
using Silksong.Rando.Data;
using Silksong.Rando.Data.Extractors;
using Silksong.Rando.Locations;
using Silksong.Rando.Logic;
using Silksong.Rando.Map;
using SkongGamemodes;
using TeamCherry.Localization;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Silksong.Rando")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.3.0")]
[assembly: AssemblyInformationalVersion("0.1.3+68feacc47410b7d16861dc9f72980cbd34406e60")]
[assembly: AssemblyProduct("Silksong.Rando")]
[assembly: AssemblyTitle("Rando")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/timothymarriott/Silksong-Rando")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
[HarmonyPatch(typeof(Language), "Get", new Type[]
{
	typeof(string),
	typeof(string)
})]
internal class Language_Get_Patch
{
	public static bool Prefix(ref string __result, string key, string sheetTitle)
	{
		if (sheetTitle == "Rando")
		{
			__result = key;
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(Language), "Has", new Type[]
{
	typeof(string),
	typeof(string)
})]
internal class Language_Has_Patch
{
	public static bool Prefix(ref bool __result, string key, string sheetTitle)
	{
		if (sheetTitle == "Rando")
		{
			__result = true;
			return false;
		}
		return true;
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Generated
{
	public static class BuildConstants
	{
		public const string Version = "0.1.3";

		public const string GitHubRepo = "timothymarriott/Silksong-Rando";
	}
}
namespace Silksong.Rando
{
	public static class AssemblyExtensions
	{
		public static Sprite LoadEmbeddedSprite(this Assembly asm, string path, float pixelsPerUnit = 64f)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			using Stream stream = asm.GetManifestResourceStream(path);
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val = new Texture2D(2, 2);
			ImageConversion.LoadImage(val, array, false);
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), Vector2.one * 0.5f, pixelsPerUnit);
		}

		public static string LoadEmbeddedText(this Assembly asm, string path)
		{
			using Stream stream = asm.GetManifestResourceStream(path);
			if (stream == null)
			{
				throw new InvalidOperationException("Resource not found: " + path);
			}
			using StreamReader streamReader = new StreamReader(stream);
			return streamReader.ReadToEnd();
		}
	}
	public abstract class DataBuilder<TResult>
	{
		public TResult result;

		public bool IsBuilt { get; protected set; }
	}
	public class ModResources : MonoBehaviour
	{
		public static ManualLogSource Logger;

		private static Dictionary<string, Sprite> Images = new Dictionary<string, Sprite>();

		private static Dictionary<string, string> Data = new Dictionary<string, string>();

		public Font trajanBold;

		public Font trajanNormal;

		public Font arial;

		public static Sprite LoadSprite(string id, float pixelsPerUnit = 64f)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!Images.TryGetValue(id, out Sprite value))
			{
				return Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 4f, 4f), Vector2.one * 0.5f, pixelsPerUnit);
			}
			return value;
		}

		public static string LoadData(string id)
		{
			if (!Data.TryGetValue(id, out string value))
			{
				throw new KeyNotFoundException(id);
			}
			return value;
		}

		public static Stream GetResourceStream(string id)
		{
			string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
			foreach (string text in manifestResourceNames)
			{
				if (text.EndsWith(".json") && text.StartsWith("Silksong.Rando.Resources.") && text.Substring("Silksong.Rando.Resources.".Length).Replace(".json", "").Replace(".png", "")
					.Replace('.', '/') == id)
				{
					return Assembly.GetExecutingAssembly().GetManifestResourceStream(text);
				}
			}
			throw new FileNotFoundException();
		}

		public static AssetBundle LoadAssetBundle(string id)
		{
			string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
			foreach (string text in manifestResourceNames)
			{
				if (text.EndsWith(".bundle") && text.StartsWith("Silksong.Rando.Resources.") && text.Substring("Silksong.Rando.Resources.".Length).Replace(".bundle", "").Replace('.', '/') == id)
				{
					Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text);
					using MemoryStream memoryStream = new MemoryStream();
					manifestResourceStream.CopyTo(memoryStream);
					return AssetBundle.LoadFromMemory(memoryStream.ToArray());
				}
			}
			throw new FileNotFoundException();
		}

		public static ModResources LoadResources(ManualLogSource logger)
		{
			Logger = logger;
			string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
			foreach (string text in manifestResourceNames)
			{
				if (text.EndsWith(".png") && text.StartsWith("Silksong.Rando.Resources.Images."))
				{
					try
					{
						string text2 = text.Substring("Silksong.Rando.Resources.Images.".Length).Replace(".png", "").Replace('.', '/');
						Images.Add(text2, Assembly.GetExecutingAssembly().LoadEmbeddedSprite(text));
						Logger.LogInfo((object)("Loaded image: " + text2));
					}
					catch (Exception ex)
					{
						Logger.LogInfo((object)("Failed to load image: " + text + "\n" + ex.ToString()));
					}
				}
				if (text.EndsWith(".json") && text.StartsWith("Silksong.Rando.Resources."))
				{
					string key = text.Substring("Silksong.Rando.Resources.".Length).Replace(".json", "").Replace('.', '/');
					Data.Add(key, Assembly.GetExecutingAssembly().LoadEmbeddedText(text));
				}
			}
			return ((Component)RandoPlugin.instance).gameObject.AddComponent<ModResources>();
		}

		private void Update()
		{
			if (!((Object)(object)trajanBold == (Object)null) && !((Object)(object)trajanNormal == (Object)null) && !((Object)(object)arial == (Object)null))
			{
				return;
			}
			Font[] array = Resources.FindObjectsOfTypeAll<Font>();
			foreach (Font val in array)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name == "TrajanPro-Bold")
				{
					trajanBold = val;
				}
				if ((Object)(object)val != (Object)null && ((Object)val).name == "TrajanPro-Regular")
				{
					trajanNormal = val;
				}
				if ((Object)(object)val != (Object)null && ((Object)val).name == "Perpetua")
				{
					arial = val;
				}
			}
		}

		public static Font GetFont()
		{
			return RandoPlugin.instance.resources.arial;
		}

		public static GUIStyle GetLabelStyle()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_002b: Expected O, but got Unknown
			return new GUIStyle
			{
				fontSize = 30,
				fontStyle = (FontStyle)0,
				normal = new GUIStyleState
				{
					textColor = Color.white
				}
			};
		}
	}
	public class PlayerDataDelegateTestGroup : PlayerDataTest
	{
		public delegate bool IsFulfilledCallback(PlayerData data);

		private static bool initialised;

		private static Hook? isFulfilledHook;

		private readonly IsFulfilledCallback callback;

		public PlayerDataDelegateTestGroup(IsFulfilledCallback callback)
		{
			this.callback = callback;
			if (!initialised)
			{
				initialised = true;
				HookIsFulfilled();
			}
		}

		private static void HookIsFulfilled()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			isFulfilledHook = new Hook((MethodBase)typeof(PlayerDataTest).GetProperty("IsFulfilled", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(), (Delegate)new Func<Func<PlayerDataTest, bool>, PlayerDataTest, bool>(IsFulfilledDetour));
		}

		private static bool IsFulfilledDetour(Func<PlayerDataTest, bool> orig, PlayerDataTest self)
		{
			if (self is PlayerDataDelegateTestGroup playerDataDelegateTestGroup)
			{
				return playerDataDelegateTestGroup.callback(RandoPlugin.GM.playerData);
			}
			return orig(self);
		}
	}
	public class RandoItem : CollectableItemBasic
	{
		public delegate void OnCollectedCallback(RandoItem item);

		public string targetItem;

		public string check;

		public SavedItem wrapped;

		public OnCollectedCallback? CollectCallback;

		public override void OnCollected()
		{
			((CollectableItemBasic)this).OnCollected();
			RandoPlugin.Log.LogInfo((object)("Collected " + targetItem));
			SaveData.Instance.CollectedChecks.Add(check);
			if ((Object)(object)wrapped != (Object)null)
			{
				((CollectableItem)this).Take(1, false);
				RandoPlugin.Log.LogInfo((object)("Giving wrapped item: " + ((Object)wrapped).name + " at " + check + "(" + ((wrapped is RandoItem randoItem) ? randoItem.check : "vanilla wrapped") + ")"));
				wrapped.Get(false);
			}
			else if (CollectCallback != null)
			{
				CollectCallback(this);
			}
			RandoPlugin.instance.map.Refresh();
		}

		public static RandoItem Wrap(string targetItem, string check, SavedItem template)
		{
			RandoItemBuilder randoItemBuilder = RandoItemBuilder.Create(targetItem, check);
			((Object)randoItemBuilder.result).name = targetItem + "_wrap";
			((CollectableItemBasic)randoItemBuilder.result).icon = template.GetPopupIcon();
			((CollectableItemBasic)randoItemBuilder.result).tinyIcon = template.GetPopupIcon();
			if (template is RandoItem randoItem)
			{
				randoItem.check = check;
			}
			randoItemBuilder.result.wrapped = template;
			randoItemBuilder.SetDisplayName(template.GetPopupName());
			return randoItemBuilder.Build();
		}
	}
	public class RandoItemBuilder : DataBuilder<RandoItem>
	{
		private static List<RandoItemBuilder> created = new List<RandoItemBuilder>();

		public static RandoItemBuilder Create(string targetItem, string check)
		{
			RandoItemBuilder randoItemBuilder = new RandoItemBuilder();
			randoItemBuilder.result = ScriptableObject.CreateInstance<RandoItem>();
			((Object)randoItemBuilder.result).name = targetItem;
			randoItemBuilder.result.targetItem = targetItem;
			((CollectableItem)randoItemBuilder.result).isHidden = true;
			randoItemBuilder.result.check = check;
			randoItemBuilder.Setup();
			created.Add(randoItemBuilder);
			return randoItemBuilder;
		}

		private void Setup()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			((CollectableItemBasic)result).isAlwaysUnlocked = true;
			((CollectableItemBasic)result).displayButtonPrompt = false;
			((CollectableItem)result).useResponses = (UseResponse[])(object)new UseResponse[1]
			{
				new UseResponse
				{
					UseType = (UseTypes)0
				}
			};
			((CollectableItemBasic)result).setExtraPlayerDataBools = (PlayerDataBoolOperation[])(object)new PlayerDataBoolOperation[0];
			((CollectableItemBasic)result).setExtraPlayerDataInts = (PlayerDataIntOperation[])(object)new PlayerDataIntOperation[0];
		}

		public RandoItemBuilder SetMaxAmount(int amount)
		{
			((CollectableItem)result).customMaxAmount = amount;
			return this;
		}

		public RandoItemBuilder SetDisplayName(string name)
		{
			return SetDisplayName("Rando", name);
		}

		public RandoItemBuilder SetDisplayName(string sheet, string key)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return SetDisplayName(new LocalisedString(sheet, key));
		}

		public RandoItemBuilder SetDisplayName(LocalisedString name)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			((CollectableItemBasic)result).displayName = name;
			return this;
		}

		public RandoItemBuilder SetDescription(string description)
		{
			return SetDescription("Rando", description);
		}

		public RandoItemBuilder SetDescription(string sheet, string key)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return SetDescription(new LocalisedString(sheet, key));
		}

		public RandoItemBuilder SetDescription(LocalisedString description)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			((CollectableItemBasic)result).description = description;
			return this;
		}

		public RandoItemBuilder SetIcon(Sprite sprite)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sprite == (Object)null)
			{
				return this;
			}
			Rect rect = sprite.rect;
			int num = (int)((Rect)(ref rect)).width;
			rect = sprite.rect;
			int num2 = (int)((Rect)(ref rect)).height;
			if (num <= 120 && num2 <= 120)
			{
				((CollectableItemBasic)result).icon = sprite;
				((CollectableItemBasic)result).tinyIcon = sprite;
				return this;
			}
			float num3 = Mathf.Min(120f / (float)num, 120f / (float)num2);
			int num4 = Mathf.RoundToInt((float)num * num3);
			int num5 = Mathf.RoundToInt((float)num2 * num3);
			Texture2D texture = sprite.texture;
			Rect rect2 = sprite.rect;
			Color[] pixels = texture.GetPixels((int)((Rect)(ref rect2)).x, (int)((Rect)(ref rect2)).y, (int)((Rect)(ref rect2)).width, (int)((Rect)(ref rect2)).height);
			Texture2D val = new Texture2D(num4, num5, texture.format, false);
			((Texture)val).filterMode = (FilterMode)1;
			for (int i = 0; i < num5; i++)
			{
				for (int j = 0; j < num4; j++)
				{
					float num6 = (float)j / (float)(num4 - 1);
					float num7 = (float)i / (float)(num5 - 1);
					int num8 = Mathf.RoundToInt(num6 * (float)(num - 1));
					int num9 = Mathf.RoundToInt(num7 * (float)(num2 - 1));
					val.SetPixel(j, i, pixels[num9 * num + num8]);
				}
			}
			val.Apply();
			Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)num4, (float)num5), new Vector2(0.5f, 0.5f), sprite.pixelsPerUnit);
			((CollectableItemBasic)result).icon = val2;
			((CollectableItemBasic)result).tinyIcon = val2;
			return this;
		}

		public RandoItemBuilder SetIcon(string icon)
		{
			return SetIcon(ModResources.LoadSprite(icon));
		}

		public RandoItemBuilder SetTinyIcon(Sprite sprite)
		{
			((CollectableItemBasic)result).tinyIcon = sprite;
			return this;
		}

		public RandoItemBuilder SetTinyIcon(string icon)
		{
			return SetTinyIcon(ModResources.LoadSprite(icon));
		}

		public RandoItemBuilder SetCollectCallback(RandoItem.OnCollectedCallback action)
		{
			result.CollectCallback = action;
			return this;
		}

		public RandoItem Build()
		{
			if (base.IsBuilt)
			{
				return result;
			}
			base.IsBuilt = true;
			((NamedScriptableObjectList<CollectableItem>)(object)ManagerSingleton<CollectableItemManager>.Instance.masterList).Add((CollectableItem)(object)result);
			return result;
		}
	}
	[BepInPlugin("com.lem00ns.Silksong.Rando", "Randomiser", "0.1.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class RandoPlugin : BaseUnityPlugin, ISaveDataMod<SaveData>, ISaveDataMod
	{
		public const string Id = "com.lem00ns.Silksong.Rando";

		public const string Name = "Randomiser";

		public static RandoPlugin instance;

		public static GameManager GM;

		public ModResources resources;

		public SceneLoader sceneLoader;

		public RandoMap map;

		public LogicFile logic;

		public long versionStatus;

		private string versionStatusText;

		private bool versionOutOfDate;

		private string latestVersion;

		public List<CollectableItemPickup> PickupsToIgnore = new List<CollectableItemPickup>();

		public GameModeData GameMode;

		public Dictionary<string, SavedItem> AddressableItems = new Dictionary<string, SavedItem>();

		public bool ShowSceneDebug;

		public List<(string target, string check, SavedItem itm)> CollectableCache = new List<(string, string, SavedItem)>();

		SaveData? ISaveDataMod<SaveData>.SaveData
		{
			get
			{
				return SaveData.Instance;
			}
			set
			{
				SaveData.Instance = value;
			}
		}

		public static ManualLogSource Log => ((BaseUnityPlugin)instance).Logger;

		public Dictionary<string, string> ItemReplacements => SaveData.Instance.ItemReplacements;

		private void Awake()
		{
			instance = this;
			resources = ModResources.LoadResources(((BaseUnityPlugin)this).Logger);
			GameScenes.Load();
			sceneLoader = SceneLoader.Setup();
			map = ((Component)this).gameObject.AddComponent<RandoMap>();
			((Component)this).gameObject.AddComponent<LocationFinder>();
			((Component)this).gameObject.AddComponent<SceneDumper>();
			logic = LogicFile.Load("logic");
			GameMode = GameModeManagerPlugin.Instance.Manager.Init((MonoBehaviour)(object)this, "Randomiser", "Basic randomiser", (Color?)null, false, (Sprite)null);
			MossberryLocation.InstallHooks();
			CollectableItemPickupLocation.InstallHooks();
			VersionInfo.FetchInfo(delegate(long status, string statusText, bool outOfDate, string latest)
			{
				latestVersion = latest;
				versionOutOfDate = outOfDate;
				versionStatusText = statusText;
				versionStatus = status;
			});
		}

		private void Start()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			new Harmony("com.lem00ns.Silksong.Rando").PatchAll(typeof(RandoPlugin).Assembly);
		}

		private void OnGUI()
		{
			//IL_0089: 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_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//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)
			if (!Object.op_Implicit((Object)(object)GM))
			{
				return;
			}
			GUI.skin.font = ModResources.GetFont();
			List<(string txt, Color color)> DebugTexts = new List<(string, Color)>();
			AddLine("Randomiser by Lem00ns - alpha v0.1.3 - Expect Bugs!");
			if (versionStatus == 0L)
			{
				AddLine("Fetching latest version info...");
			}
			else if (versionStatus == 200)
			{
				if (versionOutOfDate)
				{
					AddColoredLine("Randomiser out of date, latest version is " + latestVersion + " your version is 0.1.3 please update the mod.", Color.red);
				}
			}
			else
			{
				AddColoredLine(versionStatusText, Color.red);
			}
			if (ShowSceneDebug)
			{
				AddLine(GM.GetSceneNameString());
			}
			if (PlayerData.instance != null)
			{
				if (ShowSceneDebug)
				{
					TransitionPoint val = null;
					float num = float.MaxValue;
					foreach (TransitionPoint transitionPoint in TransitionPoint.TransitionPoints)
					{
						Scene scene = ((Component)transitionPoint).gameObject.scene;
						if (((Scene)(ref scene)).name == GM.GetSceneNameString())
						{
							float num2 = Vector2.Distance(Vector2.op_Implicit(((Component)transitionPoint).transform.position), Vector2.op_Implicit(GM.hero_ctrl.transform.position));
							if (num2 < num)
							{
								num = num2;
								val = transitionPoint;
							}
						}
					}
					if ((Object)(object)val != (Object)null)
					{
						AddLine($"{((Object)val).name} - {num}m");
					}
				}
				if (PlayerData.instance.isInventoryOpen)
				{
					AddLine($"{map.mode} map.");
				}
			}
			for (int i = 0; i < DebugTexts.Count; i++)
			{
				GUIStyle labelStyle = ModResources.GetLabelStyle();
				GUI.contentColor = DebugTexts[i].color;
				GUI.Label(new Rect(10f, (float)Screen.height - (40f + (float)(i * 30)), 100f, 100f), DebugTexts[i].txt, labelStyle);
			}
			void AddColoredLine(string txt, Color color)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				DebugTexts.Add((txt, color));
			}
			void AddLine(string txt)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				AddColoredLine(txt, Color.white);
			}
		}

		private void Update()
		{
			if (Object.op_Implicit((Object)(object)GameManager.SilentInstance) && !Object.op_Implicit((Object)(object)GM))
			{
				GM = GameManager.instance;
			}
			if (Input.GetKeyDown((KeyCode)99) && Input.GetKey((KeyCode)292))
			{
				ShowSceneDebug = !ShowSceneDebug;
			}
			if (!Input.GetKeyDown((KeyCode)98) || !Input.GetKey((KeyCode)292))
			{
				return;
			}
			Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
			foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles())
			{
				try
				{
					dictionary.Add(((Object)allLoadedAssetBundle).name, allLoadedAssetBundle.GetAllAssetNames().ToList());
				}
				catch
				{
				}
			}
			File.WriteAllText(Application.persistentDataPath + "/rando/bundles.json", JsonConvert.SerializeObject((object)dictionary, (Formatting)1));
		}

		private AssetBundle FindBundleContaining(string req)
		{
			foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles())
			{
				try
				{
					string[] allAssetNames = allLoadedAssetBundle.GetAllAssetNames();
					for (int i = 0; i < allAssetNames.Length; i++)
					{
						if (allAssetNames[i].Contains(req))
						{
							return allLoadedAssetBundle;
						}
					}
				}
				catch
				{
				}
			}
			return null;
		}

		public void LoadFakeCollectables()
		{
			AddressableItems.Clear();
			FakeCollectable[] array = FindBundleContaining("Fake Collectables").LoadAllAssets<FakeCollectable>();
			foreach (FakeCollectable val in array)
			{
				AddressableItems.Add(((Object)val).name, (SavedItem)(object)val);
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		private static SavedItem CreateCollectableItem(string target, string check)
		{
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Expected I4, but got Unknown
			if ((Object)(object)((NamedScriptableObjectList<CollectableItem>)(object)ManagerSingleton<CollectableItemManager>.Instance.masterList).GetByName(target) != (Object)null)
			{
				return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)((NamedScriptableObjectList<CollectableItem>)(object)ManagerSingleton<CollectableItemManager>.Instance.masterList).GetByName(target));
			}
			if ((Object)(object)((NamedScriptableObjectList<ToolItem>)(object)ManagerSingleton<ToolItemManager>.Instance.toolItems).GetByName(target) != (Object)null)
			{
				return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)((NamedScriptableObjectList<ToolItem>)(object)ManagerSingleton<ToolItemManager>.Instance.toolItems).GetByName(target));
			}
			if ((Object)(object)CollectableRelicManager.GetRelic(target) != (Object)null)
			{
				return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)CollectableRelicManager.GetRelic(target));
			}
			if (instance.AddressableItems.ContainsKey(target))
			{
				return (SavedItem)(object)RandoItem.Wrap(target, check, instance.AddressableItems[target]);
			}
			if (target.StartsWith("georock_"))
			{
				return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)((NamedScriptableObjectList<CollectableItem>)(object)ManagerSingleton<CollectableItemManager>.Instance.masterList).GetByName("Rosary_Set_Small"));
			}
			RandoItemBuilder randoItemBuilder = RandoItemBuilder.Create(target, check);
			randoItemBuilder.SetDisplayName("Invalid Item");
			randoItemBuilder.SetDescription("Internal Item for the randomiser");
			randoItemBuilder.SetMaxAmount(int.MaxValue);
			if (target.EndsWith(" Map"))
			{
				randoItemBuilder.SetDisplayName(target);
				randoItemBuilder.SetIcon("Map");
			}
			else
			{
				randoItemBuilder.SetIcon("missing");
			}
			RandoItem.OnCollectedCallback onCollectedCallback = null;
			if (target == "Brolly")
			{
				randoItemBuilder.SetDisplayName("Float Cloak");
				randoItemBuilder.SetIcon("DriftersCloak");
				onCollectedCallback = delegate
				{
					GM.playerData.hasBrolly = true;
				};
			}
			if (target == "Faydown")
			{
				randoItemBuilder.SetDisplayName("Faydown Cloak");
				randoItemBuilder.SetIcon("FaydownCloak");
				onCollectedCallback = delegate
				{
					GM.playerData.hasDoubleJump = true;
				};
			}
			if (target == "melody_Vault")
			{
				randoItemBuilder.SetDisplayName("Vaultkeeper's Melody");
				randoItemBuilder.SetIcon("VaultkeepersMelody");
				onCollectedCallback = delegate
				{
					GM.playerData.HasMelodyLibrarian = true;
				};
			}
			if (target == "melody_Conductor")
			{
				randoItemBuilder.SetDisplayName("Conductor's Melody");
				randoItemBuilder.SetIcon("ConductorsMelody");
				onCollectedCallback = delegate
				{
					GM.playerData.HasMelodyConductor = true;
				};
			}
			if (target == "melody_Architect")
			{
				randoItemBuilder.SetDisplayName("Architects's Melody");
				randoItemBuilder.SetIcon("ArchitectsMelody");
				onCollectedCallback = delegate
				{
					GM.playerData.HasMelodyArchitect = true;
				};
			}
			if (target.StartsWith("ability_"))
			{
				WeaverSpireAbility val = Enum.Parse<WeaverSpireAbility>(target.Replace("ability_", ""));
				switch ((int)val)
				{
				case 0:
					return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)ToolItemManager.GetToolByName("Silk Spear"));
				case 8:
					return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)ToolItemManager.GetToolByName("Silk Bomb"));
				case 4:
					return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)ToolItemManager.GetToolByName("Silk Charge"));
				case 2:
					return (SavedItem)(object)RandoItem.Wrap(target, check, (SavedItem)(object)ToolItemManager.GetToolByName("Thread Sphere"));
				case 5:
					randoItemBuilder.SetDisplayName("Clawline");
					randoItemBuilder.SetIcon("Icon_SS_Clawline");
					onCollectedCallback = delegate
					{
						GM.playerData.hasHarpoonDash = true;
					};
					break;
				case 6:
					randoItemBuilder.SetDisplayName("Needolin");
					randoItemBuilder.SetIcon("Icon_SS_Needolin");
					onCollectedCallback = delegate
					{
						GM.playerData.hasNeedolin = true;
					};
					break;
				case 1:
					randoItemBuilder.SetDisplayName("Swift Step");
					randoItemBuilder.SetIcon("Icon_SS_Swift_Step");
					onCollectedCallback = delegate
					{
						GM.playerData.hasDash = true;
					};
					break;
				case 7:
					randoItemBuilder.SetDisplayName("Silk Soar");
					randoItemBuilder.SetIcon("Icon_SS_Silk_Soar");
					onCollectedCallback = delegate
					{
						GM.playerData.hasSuperJump = true;
					};
					break;
				case 3:
					randoItemBuilder.SetDisplayName("Cling Grip");
					randoItemBuilder.SetIcon("Icon_SS_Cling_Grip");
					onCollectedCallback = delegate
					{
						GM.playerData.hasWalljump = true;
					};
					break;
				}
			}
			if (onCollectedCallback != null)
			{
				randoItemBuilder.SetCollectCallback(onCollectedCallback);
			}
			return (SavedItem)(object)randoItemBuilder.Build();
		}

		public static SavedItem GetCollectableItem(string target, string check)
		{
			foreach (var item in instance.CollectableCache)
			{
				if (item.target == target && item.check == check)
				{
					return item.itm;
				}
			}
			SavedItem val = CreateCollectableItem(target, check);
			instance.CollectableCache.Add((target, check, val));
			return val;
		}
	}
	public class SaveData
	{
		private static SaveData? _instance;

		public static SaveData Instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new SaveData();
				}
				return _instance;
			}
			[param: AllowNull]
			internal set
			{
				_instance = value;
			}
		}

		public int RandoSeed { get; set; } = -1;


		public Dictionary<string, string> ItemReplacements { get; set; } = new Dictionary<string, string>();


		public List<string> CollectedChecks { get; set; } = new List<string>();


		public static void Clear()
		{
			Instance = new SaveData();
		}
	}
	public class SceneLoader : MonoBehaviour
	{
		public delegate void OnSceneCallback(string scene, int index);

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

			private object <>2__current;

			public List<string> scenes;

			public SceneLoader <>4__this;

			public OnSceneCallback OnScene;

			public Action OnComplete;

			private int <i>5__2;

			private string <scn>5__3;

			private AsyncOperationHandle<SceneInstance> <task>5__4;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				<scn>5__3 = null;
				<task>5__4 = default(AsyncOperationHandle<SceneInstance>);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0153: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				SceneLoader sceneLoader = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					Log.LogInfo((object)$"Starting task on {scenes.Count} scenes.");
					if (sceneLoader.IsLoading)
					{
						break;
					}
					sceneLoader.IsLoading = true;
					((Component)GameCameras.instance.mainCamera).GetComponent<tk2dCamera>().ZoomFactor = 0.3f;
					TimeManager.TimeScale = 0f;
					Time.timeScale = 0f;
					<i>5__2 = 0;
					goto IL_0169;
				case 1:
					<>1__state = -1;
					goto IL_00ec;
				case 2:
					<>1__state = -1;
					if (OnScene != null)
					{
						OnScene(<scn>5__3, <i>5__2);
					}
					<>2__current = null;
					<>1__state = 3;
					return true;
				case 3:
					{
						<>1__state = -1;
						<scn>5__3 = null;
						<task>5__4 = default(AsyncOperationHandle<SceneInstance>);
						<i>5__2++;
						goto IL_0169;
					}
					IL_00ec:
					if (!<task>5__4.IsDone)
					{
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					<>2__current = null;
					<>1__state = 2;
					return true;
					IL_0169:
					if (<i>5__2 < scenes.Count)
					{
						<scn>5__3 = scenes[<i>5__2];
						<task>5__4 = Addressables.LoadSceneAsync((object)("Scenes/" + <scn>5__3), (LoadSceneMode)0, true, 100, (SceneReleaseMode)0);
						goto IL_00ec;
					}
					TimeManager.TimeScale = 1f;
					Time.timeScale = 1f;
					sceneLoader.IsLoading = false;
					RandoPlugin.GM.ReturnToMainMenuNoSave();
					if (OnComplete != null)
					{
						OnComplete();
					}
					break;
				}
				return false;
			}

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

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

		public bool IsLoading;

		private static ManualLogSource Log => RandoPlugin.Log;

		public static SceneLoader Setup()
		{
			return ((Component)RandoPlugin.instance).gameObject.AddComponent<SceneLoader>();
		}

		public static void ExecuteLoad(List<string> scenes, OnSceneCallback OnScene, Action? OnComplete = null)
		{
			((MonoBehaviour)RandoPlugin.instance.sceneLoader).StartCoroutine(RandoPlugin.instance.sceneLoader.LoadAll(scenes, OnScene, OnComplete));
		}

		[IteratorStateMachine(typeof(<LoadAll>d__6))]
		public IEnumerator LoadAll(List<string> scenes, OnSceneCallback OnScene, Action? OnComplete = null)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadAll>d__6(0)
			{
				<>4__this = this,
				scenes = scenes,
				OnScene = OnScene,
				OnComplete = OnComplete
			};
		}
	}
	public static class VersionInfo
	{
		public delegate void OnFetched(long status, string statusText, bool outOfDate, string latest);

		private sealed class ProjectInfo
		{
			public string AssemblyTitle;

			public string Version;

			public string GitHubRepo;
		}

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

			private object <>2__current;

			public OnFetched onFetched;

			private UnityWebRequest <request>5__2;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<request>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_0076: Invalid comparison between Unknown and I4
				bool result;
				try
				{
					switch (<>1__state)
					{
					default:
						result = false;
						break;
					case 0:
					{
						<>1__state = -1;
						string text = "https://raw.githubusercontent.com/timothymarriott/Silksong-Rando/refs/heads/main/Directory.Build.props";
						<request>5__2 = UnityWebRequest.Get(text);
						<>1__state = -3;
						<request>5__2.timeout = 30;
						<>2__current = <request>5__2.SendWebRequest();
						<>1__state = 1;
						result = true;
						break;
					}
					case 1:
						<>1__state = -3;
						if ((int)<request>5__2.result != 1)
						{
							onFetched(<request>5__2.responseCode, "Failed to fetch latest version error code " + <request>5__2.responseCode, outOfDate: false, "");
							result = false;
						}
						else
						{
							ProjectInfo projectInfo = ParseProjectXml(<request>5__2.downloadHandler.text);
							Version result3;
							if (!Version.TryParse("0.1.3", out Version result2))
							{
								onFetched(0L, "Current version \"0.1.3\" is invalid.", outOfDate: true, projectInfo.Version);
								result = false;
							}
							else if (!Version.TryParse(projectInfo.Version, out result3))
							{
								onFetched(0L, "Latest version \"" + projectInfo.Version + "\" is invalid.", outOfDate: false, projectInfo.Version);
								result = false;
							}
							else
							{
								onFetched(<request>5__2.responseCode, "", result2 < result3, projectInfo.Version);
								result = false;
							}
						}
						<>m__Finally1();
						break;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
				return result;
			}

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

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<request>5__2 != null)
				{
					((IDisposable)<request>5__2).Dispose();
				}
			}

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

		public static void FetchInfo(OnFetched onFetched)
		{
			((MonoBehaviour)RandoPlugin.instance).StartCoroutine(fetchInfo(onFetched));
		}

		[IteratorStateMachine(typeof(<fetchInfo>d__2))]
		private static IEnumerator fetchInfo(OnFetched onFetched)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <fetchInfo>d__2(0)
			{
				onFetched = onFetched
			};
		}

		private static ProjectInfo ParseProjectXml(string xml)
		{
			XElement xElement = XDocument.Parse(xml).Root?.Element("PropertyGroup");
			return new ProjectInfo
			{
				AssemblyTitle = xElement.Element("AssemblyTitle")?.Value,
				Version = xElement.Element("Version")?.Value,
				GitHubRepo = xElement.Element("GitHubRepo")?.Value
			};
		}
	}
}
namespace Silksong.Rando.Data
{
	public static class GameScenes
	{
		public static Dictionary<string, SceneInfo> Scenes = new Dictionary<string, SceneInfo>();

		public static List<string> SceneNames = new List<string>
		{
			"Tut_01", "Tut_01b", "Tut_02", "Tut_03", "Tut_04", "Tut_05", "Mosstown_01", "Mosstown_02", "Mosstown_02c", "Mosstown_03",
			"Aspid_01", "Crawl_01", "Crawl_02", "Crawl_03", "Crawl_03b", "Crawl_04", "Crawl_05", "Crawl_06", "Crawl_07", "Crawl_08",
			"Crawl_09", "Crawl_10", "Belltown", "Belltown_04", "Belltown_06", "Belltown_07", "Belltown_08", "Belltown_Shrine", "Belltown_Room_pinsmith", "Belltown_Room_shellwood",
			"Belltown_Room_doctor", "Belltown_Room_Relic", "Belltown_basement", "Belltown_basement_03", "Bellway_01", "Bellway_01_boss", "Bellway_02", "Bellway_02_boss", "Bellway_03", "Bellway_03_boss",
			"Bellway_04", "Bellway_04_boss", "Bellway_08", "Bellway_City", "Bellway_Peak", "Bellway_Peak_02", "Bellway_Shadow", "Bellway_Aqueduct", "Bellway_Centipede_Arena", "Bellway_Centipede_additive",
			"Bellshrine", "Bellshrine_02", "Bellshrine_03", "Bellshrine_05", "Bellshrine_Enclave", "Bellshrine_Coral", "Bellshrine_Lore_Additive", "Bonetown", "Bonegrave", "Bone_01",
			"Bone_01b", "Bone_01c", "Bone_02", "Bone_03", "Bone_04", "Bone_05", "Bone_05_boss", "Bone_05_bellway", "Bone_05b", "Bone_06",
			"Bone_07", "Bone_08", "Bone_09", "Bone_10", "Bone_11", "Bone_11b", "Bone_12", "Bone_14", "Bone_15", "Bone_16",
			"Bone_17", "Bone_18", "Bone_19", "Ant_02", "Ant_03", "Ant_04", "Ant_04_mid", "Ant_04_left", "Ant_05b", "Ant_05c",
			"Ant_08", "Ant_09", "Ant_14", "Ant_17", "Ant_19", "Ant_20", "Ant_21", "Ant_Merchant", "Ant_Queen", "Dock_01",
			"Dock_02", "Dock_02b", "Dock_03", "Dock_03b", "Dock_03c", "Dock_03d", "Dock_04", "Dock_05", "Dock_06_Church", "Dock_08",
			"Dock_09", "Dock_10", "Dock_11", "Dock_12", "Dock_13", "Dock_14", "Dock_15", "Dock_16", "Room_Forge", "Bone_East_01",
			"Bone_East_02", "Bone_East_02b", "Bone_East_03", "Bone_East_04", "Bone_East_04c", "Bone_East_04b", "Bone_East_05", "Bone_East_07", "Bone_East_08", "Bone_East_09",
			"Bone_East_09b", "Bone_East_10", "Bone_East_10_Church", "Bone_East_10_Room", "Bone_East_11", "Bone_East_12", "Bone_East_13", "Bone_East_14", "Bone_East_14b", "Bone_East_15",
			"Bone_East_16", "Bone_East_17", "Bone_East_17b", "Bone_East_18", "Bone_East_18b", "Bone_East_18c", "Bone_East_20", "Bone_East_21", "Bone_East_22", "Bone_East_24",
			"Bone_East_25", "Bone_East_Weavehome", "Bone_East_Umbrella", "Bone_East_LavaChallenge", "Halfway_01", "Greymoor_01", "Greymoor_02", "Greymoor_03", "Greymoor_04", "Greymoor_05",
			"Greymoor_05_boss", "Greymoor_06", "Greymoor_07", "Greymoor_08", "Greymoor_08_boss", "Greymoor_08_caravan", "Greymoor_08_mapper", "Greymoor_10", "Greymoor_11", "Greymoor_12",
			"Greymoor_13", "Greymoor_15", "Greymoor_15b", "Greymoor_16", "Greymoor_17", "Greymoor_20b", "Greymoor_20c", "Greymoor_21", "Greymoor_22", "Greymoor_24",
			"Dust_01", "Dust_02", "Dust_03", "Dust_04", "Dust_05", "Dust_06", "Dust_09", "Dust_10", "Dust_11", "Dust_12",
			"Dust_Barb", "Dust_Shack", "Dust_Chef", "Dust_Maze_01", "Dust_Maze_02", "Dust_Maze_03", "Dust_Maze_04", "Dust_Maze_05", "Dust_Maze_06", "Dust_Maze_07",
			"Dust_Maze_08", "Dust_Maze_crossing", "Dust_Maze_Last_Hall", "Dust_Maze_08_completed", "Dust_Maze_09_entrance", "Organ_01", "Shadow_01", "Shadow_02", "Shadow_03", "Shadow_04",
			"Shadow_04b", "Shadow_05", "Shadow_09", "Shadow_10", "Shadow_11", "Shadow_12", "Shadow_13", "Shadow_14", "Shadow_15", "Shadow_16",
			"Shadow_18", "Shadow_19", "Shadow_20", "Shadow_21", "Shadow_22", "Shadow_23", "Shadow_24", "Shadow_25", "Shadow_26", "Shadow_27",
			"Shadow_28", "Shadow_Weavehome", "Aqueduct_01", "Aqueduct_02", "Aqueduct_03", "Aqueduct_04", "Aqueduct_05", "Aqueduct_06", "Aqueduct_07", "Wisp_02",
			"Wisp_03", "Wisp_04", "Wisp_05", "Wisp_06", "Wisp_07", "Wisp_08", "Wisp_09", "Shellwood_01", "Shellwood_01b", "Shellwood_02",
			"Shellwood_03", "Shellwood_04b", "Shellwood_04c", "Shellwood_08", "Shellwood_08c", "Shellwood_10", "Shellwood_11", "Shellwood_11b", "Shellwood_13", "Shellwood_14",
			"Shellwood_15", "Shellwood_16", "Shellwood_18", "Shellwood_19", "Shellwood_20", "Shellwood_22", "Shellwood_25", "Shellwood_25b", "Shellwood_26", "Shellwood_Witch",
			"Shellwood_11b_Memory", "Shellgrave", "Coral_02", "Coral_03", "Coral_10", "Coral_11", "Coral_11b", "Coral_12", "Coral_19", "Coral_19b",
			"Coral_23", "Coral_24", "Coral_25", "Coral_26", "Coral_27", "Coral_28", "Coral_29", "Coral_32", "Coral_33", "Coral_34",
			"Coral_35", "Coral_35b", "Coral_36", "Coral_37", "Coral_38", "Coral_39", "Coral_40", "Coral_41", "Coral_42", "Coral_43",
			"Coral_Tower_01", "Coral_Judge_Arena", "Under_01", "Under_01b", "Under_02", "Under_03", "Under_03b", "Under_03c", "Under_03d", "Under_04",
			"Under_05", "Under_06", "Under_07", "Under_07b", "Under_07c", "Under_08", "Under_10", "Under_11", "Under_12", "Under_13",
			"Under_14", "Under_16", "Under_17", "Under_18", "Under_19", "Under_19b", "Under_19c", "Under_20", "Under_21", "Under_22",
			"Under_23", "Song_01", "Song_01b", "Song_01c", "Song_02", "Song_03", "Song_04", "Song_05", "Song_07", "Song_08",
			"Song_09", "Song_09b", "Song_10", "Song_11", "Song_12", "Song_13", "Song_14", "Song_15", "Song_17", "Song_18",
			"Song_19_entrance", "Song_20", "Song_20b", "Song_24", "Song_25", "Song_26", "Song_27", "Song_Enclave", "Song_Enclave_Tube", "Tube_Hub",
			"Ward_01", "Ward_02", "Ward_02b", "Ward_03", "Ward_04", "Ward_05", "Ward_06", "Ward_07", "Library_01", "Library_02",
			"Library_03", "Library_04", "Library_05", "Library_06", "Library_07", "Library_08", "Library_09", "Library_10", "Library_11", "Library_11b",
			"Library_12", "Library_12b", "Library_13", "Library_13b", "Library_14", "Library_15", "Library_16", "Hang_01", "Hang_02", "Hang_03",
			"Hang_03_top", "Hang_04", "Hang_06", "Hang_06b", "Hang_06_bank", "Hang_07", "Hang_08", "Hang_09", "Hang_10", "Hang_12",
			"Hang_13", "Hang_14", "Hang_15", "Hang_16", "Hang_17b", "Arborium_01", "Arborium_02", "Arborium_03", "Arborium_04", "Arborium_05",
			"Arborium_06", "Arborium_07", "Arborium_08", "Arborium_09", "Arborium_10", "Arborium_11", "Arborium_Tube", "Cog_04", "Cog_05", "Cog_06",
			"Cog_07", "Cog_08", "Cog_09", "Cog_10", "Cog_Bench", "Cog_Pass", "Cog_Dancers", "Cog_Dancers_boss", "Cradle_01", "Cradle_02",
			"Cradle_03", "Song_Tower_01", "Song_Tower_Destroyed", "Cog_09_Destroyed", "Cog_10_Destroyed", "Cradle_01_Destroyed", "Cradle_03_Destroyed", "Cradle_Destroyed_Challenge_Bench", "Cradle_Destroyed_Challenge_01", "Abandoned_town",
			"Slab_01", "Slab_02", "Slab_03", "Slab_04", "Slab_05", "Slab_06", "Slab_07", "Slab_08", "Slab_10b", "Slab_10c",
			"Slab_12", "Slab_13", "Slab_14", "Slab_15", "Slab_16", "Slab_17", "Slab_18", "Slab_19b", "Slab_20", "Slab_21",
			"Slab_22", "Slab_23", "Slab_Cell", "Slab_Cell_Creature", "Slab_Cell_Quiet", "Peak_01", "Peak_02", "Peak_04", "Peak_04c", "Peak_04d",
			"Peak_05", "Peak_05c", "Peak_05d", "Peak_05e", "Peak_06", "Peak_07", "Peak_08", "Peak_08b", "Peak_10", "Peak_12",
			"Peak_Mask_Maker", "Weave_02", "Weave_03", "Weave_04", "Weave_05b", "Weave_07", "Weave_08", "Weave_10", "Weave_11", "Weave_12",
			"Weave_13", "Weave_14", "Clover_01", "Clover_01b", "Clover_02c", "Clover_03", "Clover_04b", "Clover_05c", "Clover_06", "Clover_10",
			"Clover_10_web", "Clover_11", "Clover_16", "Clover_18", "Clover_19", "Clover_20", "Abyss_01", "Abyss_02", "Abyss_02b", "Abyss_03",
			"Abyss_04", "Abyss_05", "Abyss_06", "Abyss_07", "Abyss_08", "Abyss_09", "Abyss_11", "Abyss_12", "Abyss_13", "Bonetown_boss",
			"Room_CrowCourt", "Room_CrowCourt_02", "Room_Pinstress", "Room_Witch", "Room_Caravan_Spa", "Room_Caravan_Interior", "Room_Huntress", "Room_Diving_Bell", "Room_Diving_Bell_Abyss", "Room_Diving_Bell_Abyss_Fixed",
			"Sprintmaster_Cave", "City_Lace_cutscene", "Chapel_Wanderer", "Memory_Needolin", "Memory_First_Sinner", "Memory_Silk_Heart_BellBeast", "Memory_Silk_Heart_WardBoss", "Memory_Silk_Heart_LaceTower", "Memory_Coral_Tower", "Memory_Ant_Queen",
			"Belltown_Room_Spare", "Shadow_08", "Cradle_02b", "Slab_16b", "Clover_21", "Pre_Menu_Loader", "Bone_East_08_boss_golem", "Bone_East_08_boss_golem_rest", "Bone_East_08_boss_beastfly", "Song_28",
			"Song_29", "Aqueduct_08", "Coral_44", "Hang_04_boss", "Shadow_Bilehaven_Room", "Abyss_Cocoon", "Peak_06b", "Bone_East_26", "Bone_East_27", "Memory_Red",
			"Ward_09", "Bone_Steel_Servant", "Cradle_Destroyed_Challenge_02", "Under_27", "Ward_02_boss"
		};

		public static void Load()
		{
			Dictionary<string, SceneInfo> dictionary = JsonConvert.DeserializeObject<Dictionary<string, SceneInfo>>(ModResources.LoadData("scenes"));
			if (dictionary != null)
			{
				Scenes = dictionary;
			}
		}
	}
}
namespace Silksong.Rando.Data.Extractors
{
	[Serializable]
	public class SceneInfo
	{
		public float width;

		public float height;

		public Vector2 Size => new Vector2(width, height);
	}
	public class SceneDumper : MonoBehaviour
	{
		private void Update()
		{
			if (!Input.GetKeyDown((KeyCode)115) || !Input.GetKey((KeyCode)292))
			{
				return;
			}
			RandoPlugin.Log.LogInfo((object)"Starting to laod scene sizes");
			Dictionary<string, SceneInfo> sceneSizes = new Dictionary<string, SceneInfo>();
			SceneLoader.ExecuteLoad(GameScenes.SceneNames, delegate(string scene, int i)
			{
				RandoPlugin.Log.LogInfo((object)$"Searching {scene} ({i}/{GameScenes.SceneNames.Count})");
				try
				{
					sceneSizes.Add(scene, new SceneInfo
					{
						width = RandoPlugin.GM.tilemap.width,
						height = RandoPlugin.GM.tilemap.height
					});
				}
				catch (Exception ex)
				{
					RandoPlugin.Log.LogError((object)ex);
				}
			}, delegate
			{
				File.WriteAllText(Application.persistentDataPath + "\\rando\\scenes.json", JsonConvert.SerializeObject((object)sceneSizes, (Formatting)1));
			});
		}
	}
}
namespace Silksong.Rando.Map
{
	public enum MapMode
	{
		No,
		Checks,
		Dev,
		Spoiler
	}
	public class RandoMap : MonoBehaviour
	{
		public enum PinColor
		{
			Black,
			Red,
			Yellow,
			White,
			Bronze
		}

		public static RandoMap instance;

		public List<GameObject> CreatedMarkers = new List<GameObject>();

		public MapMode mode;

		public static GameManager GM => RandoPlugin.GM;

		private void Awake()
		{
			instance = this;
			PlayerDataVariableEvents.OnGetBool += delegate(PlayerData pd, string fieldName, bool current)
			{
				if (fieldName == "mapAllRooms")
				{
					return true;
				}
				return fieldName == "hasQuill" || current;
			};
		}

		private void Update()
		{
			if (PlayerData.instance != null && Input.GetKeyDown((KeyCode)116) && PlayerData.instance.isInventoryOpen)
			{
				mode = (MapMode)((int)(mode + 1) % 4);
				Refresh();
			}
			if (Input.GetKeyDown((KeyCode)114) && Input.GetKey((KeyCode)292))
			{
				int num = Random.Range(0, int.MaxValue);
				RandoPlugin.Log.LogInfo((object)$"Starting rando with seed {num}");
				SaveData.Instance.RandoSeed = num;
				SaveData.Instance.ItemReplacements = RandoPlugin.instance.logic.GenerateSeed(num);
				Refresh();
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		public void Refresh()
		{
			foreach (GameObject createdMarker in CreatedMarkers)
			{
				Object.Destroy((Object)(object)createdMarker);
			}
			CreateLocationPins();
		}

		public void CreateMapPin(ItemLocationData loc)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			if (mode == MapMode.Checks && !RandoPlugin.instance.logic.HasCheck(loc.GetID()))
			{
				return;
			}
			GameMapScene val = default(GameMapScene);
			GameObject val2 = default(GameObject);
			Vector2 val3 = default(Vector2);
			GM.gameMap.GetSceneInfo(loc.scene, GM.gameMap.GetMapZoneFromSceneName(loc.scene), ref val, ref val2, ref val3);
			Vector2 mapPosition = GM.gameMap.GetMapPosition(loc.PositionInScene, val, val2, val3, GameScenes.Scenes[loc.scene].Size);
			Transform val4 = GM.gameMap.compassIcon.transform.parent;
			for (int i = 0; i < GM.gameMap.compassIcon.transform.parent.childCount; i++)
			{
				if (((Object)((Component)GM.gameMap.compassIcon.transform.parent.GetChild(i)).gameObject).name == "Map Markers")
				{
					val4 = GM.gameMap.compassIcon.transform.parent.GetChild(i);
				}
			}
			PinColor pinColor = PinColor.Black;
			if (RandoPlugin.instance.logic.HasCheck(loc.GetID()))
			{
				pinColor = PinColor.White;
			}
			GameObject val5 = Object.Instantiate<GameObject>(((Component)val4.GetChild((int)pinColor)).gameObject, val4);
			CreatedMarkers.Add(val5);
			val5.transform.localScale = Vector3.one * 0.4f;
			SpriteRenderer component = val5.GetComponent<SpriteRenderer>();
			if (mode == MapMode.Dev)
			{
				if (SaveData.Instance.ItemReplacements.ContainsKey(loc.GetID()))
				{
					SavedItem collectableItem = RandoPlugin.GetCollectableItem(loc.item, loc.GetID());
					component.sprite = collectableItem.GetPopupIcon();
				}
				else
				{
					SavedItem collectableItem2 = RandoPlugin.GetCollectableItem(loc.item, loc.GetID());
					component.sprite = collectableItem2.GetPopupIcon();
					component.color = Color.green;
				}
				if (!RandoPlugin.instance.logic.HasCheck(loc.scene + "|" + loc.item))
				{
					component.color = Color.red;
				}
			}
			if (mode == MapMode.Spoiler)
			{
				if (SaveData.Instance.ItemReplacements.ContainsKey(loc.GetID()))
				{
					SavedItem collectableItem3 = RandoPlugin.GetCollectableItem(SaveData.Instance.ItemReplacements[loc.GetID()], loc.GetID());
					component.sprite = collectableItem3.GetPopupIcon();
				}
				else
				{
					SavedItem collectableItem4 = RandoPlugin.GetCollectableItem(loc.item, loc.GetID());
					component.sprite = collectableItem4.GetPopupIcon();
				}
			}
			if (mode == MapMode.Checks)
			{
				SavedItem collectableItem5 = RandoPlugin.GetCollectableItem(loc.item, loc.GetID());
				component.sprite = collectableItem5.GetPopupIcon();
			}
			if (SaveData.Instance.CollectedChecks.Contains(loc.GetID()))
			{
				component.color *= new Color(1f, 1f, 1f, 0.5f);
			}
			Extensions.SetLocalPosition2D(val5.transform, Vector2.op_Implicit(new Vector3(mapPosition.x, mapPosition.y, -1f)));
			if (!val5.activeSelf)
			{
				val5.SetActive(true);
			}
		}

		public void CreateLocationPins()
		{
			if (mode == MapMode.No)
			{
				return;
			}
			foreach (var (_, loc) in JsonConvert.DeserializeObject<Dictionary<string, ItemLocationData>>(ModResources.LoadData("locations")))
			{
				CreateMapPin(loc);
			}
		}
	}
}
namespace Silksong.Rando.Map.Hooks
{
	[HarmonyPatch(typeof(GameMap), "Start")]
	internal class GameMap_Start_Patch
	{
		public static void Postfix(GameMap __instance)
		{
			RandoMap.instance.CreateLocationPins();
			RandoPlugin.GM.UpdateGameMapWithPopup(0f);
		}
	}
}
namespace Silksong.Rando.Logic
{
	[Serializable]
	public class LogicFile
	{
		[CompilerGenerated]
		private sealed class <ParseReq>d__8 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private string <>2__current;

			private int <>l__initialThreadId;

			private string req;

			public string <>3__req;

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

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

			[DebuggerHidden]
			public <ParseReq>d__8(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (string.IsNullOrWhiteSpace(req) || req == "true")
					{
						return false;
					}
					<>2__current = req;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					return false;
				}
			}

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

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

			[DebuggerHidden]
			IEnumerator<string> IEnumerable<string>.GetEnumerator()
			{
				<ParseReq>d__8 <ParseReq>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<ParseReq>d__ = this;
				}
				else
				{
					<ParseReq>d__ = new <ParseReq>d__8(0);
				}
				<ParseReq>d__.req = <>3__req;
				return <ParseReq>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<string>)this).GetEnumerator();
			}
		}

		public string start;

		public string[] required;

		public Dictionary<string, LogicNode> nodes;

		[JsonIgnore]
		public LogicNode StartNode => nodes[start];

		public static LogicFile Load(string name)
		{
			return JsonConvert.DeserializeObject<LogicFile>(ModResources.LoadData(name));
		}

		public bool HasCheck(string id)
		{
			foreach (var (_, logicNode2) in nodes)
			{
				if (logicNode2.checks == null)
				{
					continue;
				}
				string[] checks = logicNode2.checks;
				for (int i = 0; i < checks.Length; i++)
				{
					if (checks[i] == id)
					{
						return true;
					}
				}
			}
			return false;
		}

		public Dictionary<string, string> GenerateSeed(int seed = -1)
		{
			Random rng = new Random();
			if (seed != -1)
			{
				rng = new Random(seed);
			}
			Dictionary<string, ItemLocationData>.KeyCollection keys = JsonConvert.DeserializeObject<Dictionary<string, ItemLocationData>>(ModResources.LoadData("locations")).Keys;
			Dictionary<string, string> placements = new Dictionary<string, string>();
			HashSet<string> reachable = new HashSet<string> { start };
			Dictionary<string, List<string>> nodeChecks = new Dictionary<string, List<string>>();
			string[] checks;
			foreach (KeyValuePair<string, LogicNode> node in nodes)
			{
				node.Deconstruct(out var key, out var value);
				string key2 = key;
				LogicNode logicNode = value;
				List<string> list = new List<string>();
				if (logicNode.checks != null)
				{
					checks = logicNode.checks;
					foreach (string text in checks)
					{
						if (keys.Contains(text))
						{
							list.Add(text);
						}
					}
				}
				Shuffle(list, rng);
				nodeChecks[key2] = list;
			}
			HashSet<string> obtainedItems = new HashSet<string>();
			HashSet<string> hashSet = new HashSet<string>();
			foreach (List<string> value2 in nodeChecks.Values)
			{
				foreach (string item2 in value2)
				{
					hashSet.Add(item2.Split('|')[1]);
				}
			}
			bool progress2;
			do
			{
				progress2 = false;
				while (true)
				{
					IL_019a:
					RefreshReachable(ref progress2);
					checks = reachable.ToArray();
					foreach (string key3 in checks)
					{
						NodeEdge[] array = nodes[key3].edges ?? Array.Empty<NodeEdge>();
						foreach (NodeEdge nodeEdge in array)
						{
							if (reachable.Contains(nodeEdge.to))
							{
								continue;
							}
							foreach (string item3 in ParseReq(nodeEdge.req))
							{
								if (!obtainedItems.Contains(item3))
								{
									ForcePlaceItem(item3, placements, nodes[key3].checks.ToList(), rng);
									obtainedItems.Add(item3);
									progress2 = true;
									goto IL_019a;
								}
							}
						}
					}
					break;
				}
				RefreshReachable(ref progress2);
			}
			while (progress2);
			if (reachable.Count != nodes.Count)
			{
				throw new Exception("Unreachable nodes remain after placement");
			}
			checks = required;
			foreach (string text2 in checks)
			{
				placements[GetReachableChecks(ref progress2)[0]] = text2;
				obtainedItems.Add(text2);
			}
			List<string> list2 = new List<string>();
			foreach (KeyValuePair<string, LogicNode> node2 in nodes)
			{
				checks = node2.Value.checks;
				for (int i = 0; i < checks.Length; i++)
				{
					string item = checks[i].Split("|", 2)[1];
					if (!obtainedItems.Contains(item))
					{
						list2.Add(item);
					}
				}
			}
			foreach (string reachableCheck in GetReachableChecks(ref progress2))
			{
				if (!placements.ContainsKey(reachableCheck))
				{
					if (list2.Count > 0)
					{
						placements[reachableCheck] = list2[0];
						obtainedItems.Add(list2[0]);
						list2.RemoveAt(0);
					}
					else
					{
						RandoPlugin.Log.LogWarning((object)"Ran out of items");
					}
				}
			}
			return placements;
			List<string> GetReachableChecks(ref bool progress)
			{
				List<string> list3 = new List<string>();
				RefreshReachable(ref progress);
				string[] array2 = reachable.ToArray();
				foreach (string key4 in array2)
				{
					foreach (string item4 in nodeChecks[key4])
					{
						if (!placements.ContainsKey(item4))
						{
							list3.Add(item4);
						}
					}
				}
				Shuffle(list3, rng);
				return list3;
			}
			void RefreshReachable(ref bool progress)
			{
				string[] array3 = reachable.ToArray();
				foreach (string key5 in array3)
				{
					NodeEdge[] array4 = nodes[key5].edges ?? Array.Empty<NodeEdge>();
					foreach (NodeEdge nodeEdge2 in array4)
					{
						if (!reachable.Contains(nodeEdge2.to) && EdgeSatisfied(nodeEdge2, obtainedItems))
						{
							reachable.Add(nodeEdge2.to);
							progress = true;
						}
					}
				}
			}
		}

		[IteratorStateMachine(typeof(<ParseReq>d__8))]
		private static IEnumerable<string> ParseReq(string? req)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ParseReq>d__8(-2)
			{
				<>3__req = req
			};
		}

		private static bool ForcePlaceItem(string item, Dictionary<string, string> placements, List<string> reachable, Random rng)
		{
			foreach (string item2 in Shuffled(reachable, rng))
			{
				if (!placements.ContainsKey(item2))
				{
					placements[item2] = item;
					RandoPlugin.Log.LogInfo((object)("Force placed " + item));
					return true;
				}
			}
			return false;
		}

		private static bool EdgeSatisfied(NodeEdge edge, HashSet<string> obtainedItems)
		{
			if (string.IsNullOrWhiteSpace(edge.req) || edge.req == "true")
			{
				return true;
			}
			if (!obtainedItems.Contains(edge.req))
			{
				return false;
			}
			return true;
		}

		private static void Shuffle<T>(IList<T> list, Random rng)
		{
			for (int num = list.Count - 1; num > 0; num--)
			{
				int num2 = rng.Next(num + 1);
				int index = num;
				int index2 = num2;
				T value = list[num2];
				T value2 = list[num];
				list[index] = value;
				list[index2] = value2;
			}
		}

		private static IList<T> Shuffled<T>(IList<T> list, Random rng)
		{
			List<T> list2 = list.ToList();
			Shuffle(list2, rng);
			return list2;
		}
	}
	[Serializable]
	public class LogicNode
	{
		public NodeEdge[] edges;

		public string[] checks;
	}
	[Serializable]
	public class NodeEdge
	{
		public string to;

		public string req = "true";
	}
}
namespace Silksong.Rando.Locations
{
	public class BrollyLocation : ItemLocation
	{
		private PlayMakerFSM fsm;

		public BrollyLocation(PlayMakerFSM fsm)
		{
			this.fsm = fsm;
		}

		public override string GetItem()
		{
			return "Brolly";
		}

		public override void SetItem(string item)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			FsmState state = FsmUtil.GetState(fsm, "Msg");
			FsmUtil.RemoveAction(state, 3);
			FsmUtil.RemoveAction(state, 2);
			FsmUtil.RemoveAction(state, 1);
			FsmUtil.AddAction(state, (FsmStateAction)new Wait
			{
				time = FsmFloat.op_Implicit(0.5f),
				realTime = false
			});
			FsmUtil.AddLambdaMethod(state, (Action<Action>)delegate(Action fin)
			{
				AwardCollectable();
				fin();
			});
			FsmUtil.AddAction(state, (FsmStateAction)new Wait
			{
				time = FsmFloat.op_Implicit(0.5f),
				realTime = false
			});
			FsmUtil.RemoveTransitionsTo(state, "Fade Up");
			FsmUtil.AddTransition(state, "FINISHED", "Fade Up");
		}

		public override GameObject GetObj()
		{
			return ((Component)fsm).gameObject;
		}
	}
	public class CollectableItemPickupLocation : ItemLocation
	{
		private CollectableItemPickup pickup;

		public CollectableItemPickupLocation(CollectableItemPickup pickup)
		{
			this.pickup = pickup;
		}

		public override string GetItem()
		{
			return ((Object)pickup.item).name;
		}

		public override GameObject GetObj()
		{
			return ((Component)pickup).gameObject;
		}

		public override void SetItem(string item)
		{
			if (IsChecked())
			{
				Object.Destroy((Object)(object)((Component)pickup).gameObject);
			}
			else
			{
				pickup.SetItem(RandoPlugin.GetCollectableItem(item, GetLocationID()), false);
			}
		}

		public static void InstallHooks()
		{
			PlayerDataVariableEvents.OnGetInt += (PlayerData pd, string name, int current) => (name == "dicePilgrimState" && RandoPlugin.instance.GameMode.Enabled) ? 1 : current;
		}
	}
	public class DJLocation : ItemLocation
	{
		private PlayMakerFSM fsm;

		public DJLocation(PlayMakerFSM fsm)
		{
			this.fsm = fsm;
		}

		public override string GetItem()
		{
			return "Faydown";
		}

		public override void SetItem(string item)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			FsmState checkState = FsmUtil.GetState(fsm, "Has DJ?");
			FsmUtil.RemoveAction(checkState, 0);
			FsmUtil.AddLambdaMethod(checkState, (Action<Action>)delegate
			{
				if (IsChecked())
				{
					fsm.Fsm.Event(checkState.GetTransitionEvent(0));
				}
				else
				{
					fsm.Fsm.Event(checkState.GetTransitionEvent(1));
				}
			});
			FsmState state = FsmUtil.GetState(fsm, "Msg");
			FsmUtil.RemoveAction(state, 13);
			FsmUtil.RemoveAction(state, 12);
			FsmUtil.RemoveAction(state, 11);
			FsmUtil.AddAction(state, (FsmStateAction)new Wait
			{
				time = FsmFloat.op_Implicit(0.5f),
				realTime = false
			});
			FsmUtil.AddLambdaMethod(state, (Action<Action>)delegate(Action fin)
			{
				AwardCollectable();
				fin();
			});
			FsmUtil.RemoveTransitionsTo(state, "Fade Back Pause");
			FsmUtil.AddTransition(state, "FINISHED", "Fade Back Pause");
		}

		public override GameObject GetObj()
		{
			return ((Component)fsm).gameObject;
		}
	}
	public class GeoRockLocation : ItemLocation
	{
		private GeoRock rock;

		public GeoRockLocation(GeoRock rock)
		{
			this.rock = rock;
		}

		public override string GetItem()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			string id = rock.geoRockData.id;
			BreakableTypes breakableType = rock.BreakableType;
			return "georock_" + id + "_" + ((object)(BreakableTypes)(ref breakableType)).ToString();
		}

		public override GameObject GetObj()
		{
			return ((Component)rock).gameObject;
		}

		public override void SetItem(string item)
		{
			base.SetItem(item);
			Object.Destroy((Object)(object)((Component)rock).gameObject);
		}
	}
	public class HeartPieceLocation : ItemLocation
	{
		private PlayMakerFSM fsm;

		public HeartPieceLocation(PlayMakerFSM fsm)
		{
			this.fsm = fsm;
		}

		public override string GetItem()
		{
			return "Heart Piece";
		}

		public override void SetItem(string item)
		{
			//IL_006e: 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_0088: Expected O, but got Unknown
			Object.Destroy((Object)(object)((Component)fsm).gameObject.GetComponent<PersistentBoolItem>());
			FsmState state = FsmUtil.GetState(fsm, "UI");
			FsmUtil.RemoveAction(state, 1);
			FsmUtil.RemoveAction(state, 0);
			FsmUtil.AddAction(state, (FsmStateAction)(object)FsmUtil.GetAction<RemoveHeroInputBlocker>(FsmUtil.GetState(fsm, "End"), 0));
			FsmUtil.AddAction(state, FsmUtil.GetAction<FsmStateAction>(FsmUtil.GetState(fsm, "End"), 1));
			FsmUtil.AddAction(state, (FsmStateAction)new SendEventToRegister
			{
				eventName = FsmString.op_Implicit("HEART PIECE COLLECTED")
			});
			FsmUtil.AddLambdaMethod(state, (Action<Action>)delegate(Action fin)
			{
				AwardCollectable();
				PlayerData.instance.isInvincible = false;
				PlayerData.instance.disablePause = false;
				HeroController.instance.StartAnimationControl();
				HeroController.instance.RegainControl();
				HeroController.instance.AffectedByGravity(true);
				HeroController.instance.rb2d.gravityScale = HeroController.instance.DEFAULT_GRAVITY;
				HeroController.instance.currentGravity = HeroController.instance.DEFAULT_GRAVITY;
				HeroController.instance.prevGravityScale = 0f;
				fin();
			});
			FsmUtil.RemoveState(fsm, "Save Collected");
			FsmUtil.RemoveTransitions(state);
			FsmUtil.AddTransition(state, "FINISHED", "End");
		}

		public override GameObject GetObj()
		{
			return ((Component)fsm).gameObject;
		}
	}
	[Serializable]
	public class ItemLocationData
	{
		public string locationType;

		public string item;

		public string scene;

		public float positionInSceneX;

		public float positionInSceneY;

		public Vector2 PositionInScene => new Vector2(positionInSceneX, positionInSceneY);

		public string GetID()
		{
			return scene + "|" + item;
		}
	}
	public abstract class ItemLocation
	{
		public ItemLocationData locationData = new ItemLocationData();

		private string replacement;

		public abstract string GetItem();

		public string GetLocationID()
		{
			return RandoPlugin.GM.sceneName + "|" + GetItem();
		}

		public void AddToCurrentScene()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			locationData.locationType = GetType().Name;
			locationData.item = GetItem();
			locationData.scene = RandoPlugin.GM.sceneName;
			Vector2 position = GetPosition();
			locationData.positionInSceneX = position.x;
			locationData.positionInSceneY = position.y;
			if (LocationFinder.IsSearching)
			{
				LocationFinder.ItemLocations.TryAdd(GetLocationID(), this);
			}
			if (RandoPlugin.instance.GameMode.Enabled && RandoPlugin.instance.ItemReplacements.ContainsKey(GetLocationID()))
			{
				if (!SaveData.Instance.CollectedChecks.Contains(GetLocationID()))
				{
					SetReplacement(RandoPlugin.instance.ItemReplacements[GetLocationID()]);
				}
				else
				{
					SetReplacement("Already Collected");
				}
			}
		}

		public void SetReplacement(string id)
		{
			replacement = id;
			RandoPlugin.Log.LogInfo((object)(GetLocationID() + " -> " + ((RandoPlugin.instance.map.mode == MapMode.Spoiler) ? replacement : "SPOILERS") + (IsChecked() ? " checked" : " unchecked")));
			SetItem(id);
		}

		public virtual Vector2 GetPosition()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			return Vector2.op_Implicit(GetObj().transform.position);
		}

		public abstract GameObject GetObj();

		public virtual void SetItem(string item)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (!IsChecked())
			{
				((Component)CreateItemPickup(item)).transform.position = GetObj().transform.position;
			}
		}

		public void AwardCollectable()
		{
			if (!IsChecked())
			{
				RandoPlugin.GetCollectableItem(replacement, GetLocationID()).Get(1, true);
			}
		}

		public bool IsChecked()
		{
			return SaveData.Instance.CollectedChecks.Contains(GetLocationID());
		}

		public CollectableItemPickup CreateItemPickup(string item)
		{
			CollectableItemPickup component = Object.Instantiate<GameObject>(((Component)Gameplay.CollectableItemPickupPrefab).gameObject).GetComponent<CollectableItemPickup>();
			RandoPlugin.instance.PickupsToIgnore.Add(component);
			component.SetItem(RandoPlugin.GetCollectableItem(item, GetLocationID()), false);
			return component;
		}
	}
	public class LocationFinder : MonoBehaviour
	{
		public static Dictionary<string, ItemLocation> ItemLocations = new Dictionary<string, ItemLocation>();

		public static Dictionary<string, Dictionary<string, Dictionary<string, string>>> RoomChecks = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();

		public static bool IsSearching = false;

		private void Update()
		{
			if (!Input.GetKeyDown((KeyCode)121) || !Input.GetKey((KeyCode)292) || IsSearching)
			{
				return;
			}
			IsSearching = true;
			SceneLoader.ExecuteLoad(GameScenes.SceneNames, delegate(string scene, int i)
			{
				//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
				RandoPlugin.Log.LogInfo((object)$"Searching {scene} ({i}/{GameScenes.SceneNames.Count}) found {ItemLocations.Count} locations.");
				File.WriteAllLines(Application.persistentDataPath + "\\rando\\locations.txt", ItemLocations.Keys);
				Dictionary<string, ItemLocationData> dictionary = new Dictionary<string, ItemLocationData>();
				foreach (KeyValuePair<string, ItemLocation> itemLocation in ItemLocations)
				{
					dictionary.Add(itemLocation.Key, itemLocation.Value.locationData);
				}
				File.WriteAllText(Application.persistentDataPath + "\\rando\\locations.json", JsonConvert.SerializeObject((object)dictionary, (Formatting)1));
				List<string> list = new List<string>();
				foreach (TransitionPoint transitionPoint in TransitionPoint.TransitionPoints)
				{
					Scene scene2 = ((Component)transitionPoint).gameObject.scene;
					if (((Scene)(ref scene2)).name == scene)
					{
						list.Add(((Object)transitionPoint).name);
					}
				}
				Dictionary<string, Dictionary<string, string>> dictionary2 = new Dictionary<string, Dictionary<string, string>>();
				foreach (string item in list)
				{
					Dictionary<string, string> dictionary3 = new Dictionary<string, string>();
					foreach (string item2 in list)
					{
						dictionary3.Add(item2, "TRANSITION_NOTSET");
					}
					foreach (KeyValuePair<string, ItemLocation> itemLocation2 in ItemLocations)
					{
						if (itemLocation2.Value.locationData.scene == scene)
						{
							dictionary3.Add(itemLocation2.Value.locationData.item, "ITEM_NOTSET");
						}
					}
					dictionary2.Add(item, dictionary3);
				}
				RoomChecks.Add(scene, dictionary2);
				File.WriteAllText(Application.persistentDataPath + "\\rando\\room_logic.json", JsonConvert.SerializeObject((object)RoomChecks, (Formatting)1));
			}, delegate
			{
				IsSearching = false;
			});
		}
	}
	public class ArchitectMelodyLocation : ItemLocation
	{
		private PlayMakerFSM fsm;

		public ArchitectMelodyLocation(PlayMakerFSM fsm)
		{
			this.fsm = fsm;
		}

		public override string GetItem()
		{
			return "melody_Architect";
		}

		public override void SetItem(string item)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			bool num = IsChecked();
			FsmState state = FsmUtil.GetState(fsm, "Wait For Notify");
			if (num)
			{
				FsmUtil.GetAction<PlayerDataVariableTest>(state, 0).IsExpectedEvent = state.GetTransitionEvent(2);
				FsmUtil.GetAction<PlayerDataVariableTest>(state, 0).IsNotExpectedEvent = state.GetTransitionEvent(2);
			}
			else
			{
				FsmUtil.GetAction<PlayerDataVariableTest>(state, 0).IsExpectedEvent = null;
			}
			FsmState state2 = FsmUtil.GetState(fsm, "Show Prompt");
			FsmUtil.RemoveAction(state2, 0);
			FsmUtil.AddAction(state2, (FsmStateAction)new Wait
			{
				time = FsmFloat.op_Implicit(1f),
				realTime = false
			});
			FsmUtil.AddLambdaMethod(state2, (Action<Action>)delegate(Action fin)
			{
				HeroController.instance.RelinquishControl();
				RandoPlugin.GM.playerData.disableInventory = false;
				AwardCollectable();
				HeroController.instance.RegainControl();
				fin();
			});
			FsmUtil.AddAction(state2, (FsmStateAction)new Wait
			{
				time = FsmFloat.op_Implicit(0.5f),
				realTime = false
			});
			FsmUtil.RemoveTransitionsTo(state2, "Singing End");
			FsmUtil.AddTransition(state2, "FINISHED", "Singing End");
		}

		public override GameObject GetObj()
		{
			return ((Component)fsm).gameObject;
		}
	}
	public class ConductorMelodyLocation : ItemLocation
	{
		private PlayMakerFSM fsm;

		public ConductorMelodyLocation(PlayMakerFSM fsm)
		{
			this.fsm = fsm;
		}

		public override string GetItem()
		{
			return "melody_Conductor";
		}

		public override void SetItem(string item)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			FsmUtil.ReplaceAction(FsmUtil.GetState(fsm, "Has Item?"), 3, (FsmStateAction)new SetBoolValue
			{
				boolVariable = FsmUtil.GetBoolVariable(fsm, "Is Melody Quest Active"),
				boolValue = FsmBool.op_Implicit(false)
			});
			FsmUtil.GetAction<CheckQuestStateV2>(FsmUtil.GetState(fsm, "Quest Active?"), 0).NotTrackedEvent = FsmUtil.GetState(fsm, "Quest Active?").GetTransitionEvent(1);
			FsmTemplateControl fsmTemplateControl = FsmUtil.GetAction<RunFSM>(FsmUtil.GetState(fsm, "Run Melody Play Prompted"), 5).fsmTemplateControl;
			FsmState state = fsmTemplateControl.RunFsm.GetState("Give Item");
			FsmUtil.RemoveAction(state, 0);
			FsmUtil.AddAction(state, (FsmStateAction)new Wait
			{
				time = FsmFloat.op_Implicit(0.5f),
				realTime = false
			});
			FsmUtil.AddLambdaMethod(state, (Action<Action>)delegate(Action fin)
			{
				AwardCollectable();
				fin();
			});
			FsmUtil.AddAction(state, (FsmStateAction)new Wait
			{
				time = FsmFloat.op_Implicit(0.5f),
				realTime = false
			});
			FsmState state2 = fsmTemplateControl.RunFsm.GetState("UI Msg");
			FsmUtil.RemoveAction(state2, 4);
			FsmUtil.RemoveAction(state2, 3);
			FsmUtil.RemoveAction(state2, 1);
			FsmUtil.RemoveAction(state2, 0);
			FsmUtil.RemoveTransitionsTo(state2, "Stop Needolin");
			FsmUtil.AddTransition(state2, "FINISHED", "Stop Needolin");
			FsmState state3 = fsmTemplateControl.RunFsm.GetState("Stop Needolin");
			FsmUtil.RemoveTransitionsTo(state3, "Give Item");
			FsmUtil.AddTransition(state3, "FINISHED", "Give Item");
		}

		public override GameObject GetObj()
		{
			return ((Component)fsm).gameObject;
		}
	}
	public class VaultMelodyLocation : ItemLocation
	{
		private PlayMakerFSM fsm;

		public VaultMelodyLocation(PlayMakerFSM fsm)
		{
			this.fsm = fsm;
		}

		public override string GetItem()
		{
			return "melody_Vault";
		}

		public override void SetItem(string item)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			FsmTemplateControl fsmTemplateControl = FsmUtil.GetAction<RunFSM>(FsmUtil.GetState(fsm, "Needolin"), 4).fsmTemplateControl;
			FsmState state = fsmTemplateControl.RunFsm.GetState("Give Item");
			FsmUtil.RemoveAction(state, 0);
			FsmUtil.AddAction(state, (FsmStateAction)new Wait
			{
				time = FsmFloat.op_Implicit(0.5f),
				realTime = false
			});
			FsmUtil.AddLambdaMethod(state, (Action<Action>)delegate(Action fin)
			{
				AwardCollectable();
				fin();
			});
			FsmUtil.AddAction(state, (FsmStateAction)new Wait
			{
				time = FsmFloat.op_Implicit(0.5f),
				realTime = false
			});
			FsmState state2 = fsmTemplateControl.RunFsm.GetState("UI Msg");
			FsmUtil.RemoveAction(state2, 4);
			FsmUtil.RemoveAction(state2, 3);
			FsmUtil.RemoveAction(state2, 1);
			FsmUtil.RemoveAction(state2, 0);
			FsmUtil.RemoveTransitionsTo(state2, "Stop Needolin");
			FsmUtil.AddTransition(state2, "FINISHED", "Stop Needolin");
			FsmState state3 = fsmTemplateControl.RunFsm.GetState("Stop Needolin");
			FsmUtil.RemoveTransitionsTo(state3, "Give Item");
			FsmUtil.AddTransition(state3, "FINISHED", "Give Item");
		}

		public override GameObject GetObj()
		{
			return ((Component)fsm).gameObject;
		}
	}
	public enum MossberryLocationType
	{
		Vine,
		Aspid
	}
	public class MossberryLocation : ItemLocation
	{
		private MossberryLocationType locType;

		private PlayMakerFSM fsm;

		private HealthManager aspid;

		public MossberryLocation(PlayMakerFSM fsm)
		{
			locType = MossberryLocationType.Vine;
			this.fsm = fsm;
		}

		public MossberryLocation(HealthManager aspid, PlayMakerFSM fsm)
		{
			locType = MossberryLocationType.Aspid;
			this.aspid = aspid;
			this.fsm = fsm;
		}

		public override string GetItem()
		{
			return "Mossberry";
		}

		public override void SetItem(string item)
		{
			Object.Destroy((Object)(object)((Component)fsm).GetComponent<PersistentBoolItem>());
			if (locType == MossberryLocationType.Vine)
			{
				if (SaveData.Instance.CollectedChecks.Contains(GetLocationID()))
				{
					((Component)fsm).gameObject.SetActive(false);
				}
				FsmUtil.InsertLambdaMethod(fsm.fsm.GetState("Init"), 4, (Action<Action>)delegate(Action fin)
				{
					FsmState state2 = FsmUtil.GetGameObjectVariable(fsm.fsm, "Fruit").Value.GetComponent<PlayMakerFSM>().fsm.GetState("Collect");
					FsmUtil.RemoveAction(state2, 2);
					FsmUtil.InsertLambdaMethod(state2, 2, (Action<Action>)delegate(Action fin)
					{
						AwardCollectable();
						fin();
					});
					fin();
				});
			}
			else if (locType == MossberryLocationType.Aspid)
			{
				RandoPlugin.Log.LogInfo((object)aspid);
				RandoPlugin.Log.LogInfo((object)fsm);
				FsmState state = fsm.fsm.GetState("Collect");
				FsmUtil.RemoveAction(state, 2);
				FsmUtil.InsertLambdaMethod(state, 2, (Action<Action>)delegate(Action fin)
				{
					AwardCollectable();
					fin();
				});
			}
		}

		public override GameObject GetObj()
		{
			if (locType == MossberryLocationType.Vine)
			{
				return ((Component)fsm).gameObject;
			}
			if (locType == MossberryLocationType.Aspid)
			{
				return ((Component)aspid).gameObject;
			}
			return ((Component)fsm).gameObject;
		}

		public static void InstallHooks()
		{
			PlayerDataVariableEvents.OnGetBool += delegate(PlayerData pd, string name, bool current)
			{
				if (RandoPlugin.instance.GameMode.Enabled)
				{
					switch (name)
					{
					case "mosstownAspidBerryCollected":
						return SaveData.Instance.CollectedChecks.Contains("Bone_05b|Mossberry");
					case "bonegraveAspidBerryCollected":
						return SaveData.Instance.CollectedChecks.Contains("Bonegrave|Mossberry");
					case "bonetownAspidBerryCollected":
						return SaveData.Instance.CollectedChecks.Contains("Bonetown|Mossberry");
					}
				}
				return current;
			};
		}
	}
	public class NeedolinLocation : ItemLocation
	{
		private PlayMakerFSM fsm;

		public NeedolinLocation(PlayMakerFSM fsm)
		{
			this.fsm = fsm;
		}

		public override string GetItem()
		{
			return "ability_Needolin";
		}

		public override void SetItem(string item)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			FsmUtil.RemoveAction(FsmUtil.GetState(fsm, "Final Bind Burst"), 3);
			FsmState state = FsmUtil.GetState(fsm, "Get Needolin");
			FsmUtil.RemoveAction(state, 1);
			FsmUtil.AddAction(state, (FsmStateAction)new Wait
			{
				time = FsmFloat.op_Implicit(0.5f),
				realTime = false
			});
			FsmUtil.AddLambdaMethod(state, (Action<Action>)delegate(Action fin)
			{
				AwardCollectable();
				PlayerData.instance.spinnerDefeated = true;
				HeroController.instance.SetSilkRegenBlocked(true);
				PlayerData.instance.disableInventory = false;
				fin();
			});
			FsmUtil.AddAction(state, (FsmStateAction)new Wait
			{
				time = FsmFloat.op_Implicit(1f),
				realTime = false
			});
			FsmUtil.AddAction(state, (FsmStateAction)new QueueMemoryFullHeal());
			FsmUtil.AddAction(state, (FsmStateAction)new ToolsCutsceneControl
			{
				SetInCutscene = FsmBool.op_Implicit(false)
			});
			BeginSceneTransition action = FsmUtil.GetAction<BeginSceneTransition>(FsmUtil.GetState(fsm, "To Memory Scene"), 2);
			action.sceneName = FsmString.op_Implicit("Belltown_Shrine");
			action.entryGateName = FsmString.op_Implicit("door_wakeOnGround");
		}

		public override GameObject GetObj()
		{
			return ((Component)fsm).gameObject;
		}
	}
	public class PollipBulbLocation : ItemLocation
	{
		private PlayMakerFSM fsm;

		public PollipBulbLocation(PlayMakerFSM fsm)
		{
			this.fsm = fsm;
		}

		public override string GetItem()
		{
			return "Shell Flower";
		}

		public override void SetItem(string item)
		{
			Object.Destroy((Object)(object)((Component)((Component)fsm).transform.parent).GetComponent<PersistentBoolItem>());
			if (IsChecked())
			{
				((Component)((Component)fsm).transform.parent).gameObject.SetActive(false);
			}
			FsmState state = fsm.fsm.GetState("Collect");
			FsmUtil.RemoveAction(state, 6);
			FsmUtil.InsertLambdaMethod(state, 6, (Action<Action>)delegate(Action fin)
			{
				AwardCollectable();
				fin();
			});
		}

		public override GameObject GetObj()
		{
			return ((Component)fsm).gameObject;
		}
	}
	public class ShrineWeaverAbilityLocation : ItemLocation
	{
		private PlayMakerFSM fsm;

		public ShrineWeaverAbilityLocation(PlayMakerFSM fsm)
		{
			this.fsm = fsm;
		}

		public override string GetItem()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			WeaverSpireAbility val = (WeaverSpireAbility)(object)fsm.FsmVariables.EnumVariables[0].Value;
			return "ability_" + ((object)(WeaverSpireAbility)(ref val)).ToString();
		}

		public override void SetItem(string item)
		{
			base.SetItem(item);
			Object.Destroy((Object)(object)((Component)fsm).GetComponent<PlayMakerNPC>());
			Object.Destroy((Object)(object)fsm);
		}

		public override GameObject GetObj()
		{
			return ((Component)fsm).gameObject;
		}
	}
}
namespace Silksong.Rando.Locations.Hooks
{
	[HarmonyPatch(typeof(CollectableItemPickup), "Start")]
	internal class CollectableItemPickup_Start_Patch
	{
		public static void Prefix(CollectableItemPickup __instance)
		{
			if (!(__instance.item is RandoItem) && !RandoPlugin.instance.PickupsToIgnore.Contains(__instance) && ((Object)__instance.item).name != "Trobbio Quill Red" && ((Object)__instance.item).name != "Shiny Bell Goomba")
			{
				new CollectableItemPickupLocation(__instance).AddToCurrentScene();
			}
		}
	}
	[HarmonyPatch(typeof(GeoRock), "Start")]
	internal class GeoRock_Start_Patch
	{
		public static void Prefix(GeoRock __instance)
		{
		}
	}
	[HarmonyPatch(typeof(HealthManager), "Start")]
	internal class HealthManager_Start_Patch
	{
		public static void Prefix(HealthManager __instance)
		{
			if (!((Object)((Component)__instance).gameObject).name.StartsWith("Aspid Collector"))
			{
				return;
			}
			for (int i = 0; i < ((Component)__instance).transform.childCount; i++)
			{
				if (((Object)((Component)((Component)__instance).transform.GetChild(i)).gameObject).name == "Mossberry Pickup")
				{
					new MossberryLocation(__instance, ((Component)((Component)__instance).transform.GetChild(i)).GetComponent<PlayMakerFSM>()).AddToCurrentScene();
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayMakerFSM), "Start")]
	internal class PlayMakerFSM_Start_Patch
	{
		public static void Prefix(PlayMakerFSM __instance)
		{
			if (((Object)__instance).name == "Shrine Weaver Ability")
			{
				new ShrineWeaverAbilityLocation(__instance).AddToCurrentScene();
			}
			if (((Object)__instance).name == "Big Flower")
			{
				new PollipBulbLocation(((Component)((Component)__instance).transform.GetChild(1)).GetComponent<PlayMakerFSM>()).AddToCurrentScene();
			}
			if (((Object)__instance).name == "moss_berry_fruit")
			{
				new MossberryLocation(__instance).AddToCurrentScene();
			}
			if (((Object)__instance).name == "Spinner Boss" && __instance.FsmName == "Control")
			{
				new NeedolinLocation(__instance).AddToCurrentScene();
			}
			if (((Object)__instance).name == "Seamstress" && __instance.FsmName == "Dialogue")
			{
				new BrollyLocation(__instance).AddToCurrentScene();
			}
			if (((Object)__instance).name == "Librarian" && __instance.FsmName == "Dialogue" && FsmUtil.GetState(__instance, "Open Relic Board") != null)
			{
				new VaultMelodyLocation(__instance).AddToCurrentScene();
			}
			if (((Object)__instance).name == "puzzle cylinders" && __instance.FsmName == "Cylinder States")
			{
				new ArchitectMelodyLocation(__instance).AddToCurrentScene();
			}
			if (((Object)__instance).name == "Last Conductor NPC" && __instance.FsmName == "Dialogue")
			{
				new ConductorMelodyLocation(__instance).AddToCurrentScene();
			}
			if (((Object)__instance).name == "DJ Get Sequence")
			{
				new DJLocation(__instance).AddToCurrentScene();
			}
		}
	}
}
namespace Silksong.Rando.Hooks
{
	[HarmonyPatch]
	public class CollectableItemManagerHooks
	{
		public static List<string> cachedItems = new List<string>();

		[HarmonyPatch(typeof(CollectableItemManager), "Awake")]
		[HarmonyPrefix]
		public static void BeginSceneTransition(CollectableItemManager __instance)
		{
			Dictionary<string, ItemLocationData> dictionary = JsonConvert.DeserializeObject<Dictionary<string, ItemLocationData>>(ModResources.LoadData("locations"));
			if (cachedItems.Count == dictionary.Count)
			{
				return;
			}
			cachedItems.Clear();
			foreach (KeyValuePair<string, ItemLocationData> item in dictionary)
			{
				cachedItems.Add(((Object)RandoPlugin.GetCollectableItem(item.Value.item, item.Key)).name);
			}
		}

		[HarmonyPatch(typeof(CollectableItemManager), "IsItemInMasterList", new Type[] { typeof(string) })]
		[HarmonyPrefix]
		public static bool IsItemInMasterList(CollectableItemManager __instance, ref bool __result, string itemName)
		{
			if (cachedItems.Contains(itemName))
			{
				__result = true;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	public class GameManagerHooks
	{
		[HarmonyPatch(typeof(GameManager), "BeginSceneTransition", new Type[] { typeof(SceneLoadInfo) })]
		[HarmonyPostfix]
		public static void BeginSceneTransition(GameManager __instance, SceneLoadInfo info)
		{
			if (RandoPlugin.instance.GameMode.Enabled && info.SceneName == "Opening_Sequence" && SaveData.Instance.RandoSeed == -1)
			{
				int num = Random.Range(0, int.MaxValue);
				RandoPlugin.Log.LogInfo((object)$"Starting rando with seed {num}");
				SaveData.Instance.RandoSeed = num;
				SaveData.Instance.ItemReplacements = RandoPlugin.instance.logic.GenerateSeed(num);
			}
		}

		[HarmonyPatch(typeof(GameManager), "ClearSaveFile", new Type[]
		{
			typeof(int),
			typeof(Action<bool>)
		})]
		[HarmonyPostfix]
		public static void ClearSaveFile(GameManager __instance, int saveSlot, Action<bool> callback)
		{
			if (RandoPlugin.instance.GameMode.Enabled)
			{
				SaveData.Clear();
			}
		}

		[HarmonyPatch(typeof(GameManager), "Start")]
		[HarmonyPostfix]
		public static void Start(GameManager __instance)
		{
			RandoPlugin.instance.LoadFakeCollectables();
		}
	}
}