Decompiled source of MenuCleaner v1.2.2

UltrakillLayerConfigurator.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using PluginConfig.API;
using PluginConfig.API.Fields;
using Steamworks;
using TMPro;
using UltrakillLayerConfigurator.Data;
using UltrakillLayerConfigurator.Data.Layers;
using UltrakillLayerConfigurator.Patches;
using UltrakillLayerConfigurator.Scripts;
using UltrakillModLib;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("UltrakillLayerConfigurator")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+98ffb30681c4a473fb602eb6e0156488686dee0f")]
[assembly: AssemblyProduct("UltrakillLayerConfigurator")]
[assembly: AssemblyTitle("UltrakillLayerConfigurator")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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;
		}
	}
}
namespace UltrakillLayerConfigurator
{
	[BepInPlugin("net.zephyr.ultrakill.LayerConfigurator", "Menu Cleaner", "1.2.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class LayerPlugin : BaseUnityPlugin
	{
		internal static DebugLog Log;

		private PluginConfigurator config;

		public const string ModName = "Zephyr's Menu Cleaner";

		public const string ModPath = "net.zephyr.ultrakill.LayerConfigurator";

		public BoolField IgnoreUnreleasedLevels;

		private const string IgnoreUnreleasedLevelsName = "Ignore RANKS from Unreleased Levels";

		private const string ConfigLocationButtonName = "Open CONFIG Folder";

		private const string FeedbackButtonName = "Send FEEDBACK / REPORT BUG (discord)";

		public static bool IsBillionNemesisInstalled;

		public static bool IsUltraStatsInstalled;

		public static bool IsStrayModeInstalled;

		public static bool IsUltraskinsInstalled;

		public static bool IsTitleScreenQuickAccessInstalled;

		public static LayerPlugin Instance { get; private set; }

		public LayerPlugin()
		{
			Instance = this;
			CreateConfig();
		}

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			Harmony val = new Harmony("net.zephyr.ultrakill.LayerConfigurator");
			val.CreateClassProcessor(typeof(ChapterSelectButtonPatch)).Patch();
			val.CreateClassProcessor(typeof(LayerSelectPatch)).Patch();
			val.CreateClassProcessor(typeof(DifficultySelectButtonPatch)).Patch();
			val.CreateClassProcessor(typeof(GearCheckEnablerPatch)).Patch();
			val.CreateClassProcessor(typeof(GetMissionName)).Patch();
			if (Chainloader.PluginInfos.ContainsKey("billy.billionnemesis"))
			{
				val.CreateClassProcessor(typeof(BillionRankStuffPatch)).Patch();
			}
			Log = new DebugLog("Zephyr's Menu Cleaner", ConsoleColor.DarkCyan, false);
			Log.Log("The goop is in the bag.");
		}

		private void Start()
		{
			bool flag = false;
			IsBillionNemesisInstalled = Chainloader.PluginInfos.ContainsKey("billy.billionnemesis");
			if (IsBillionNemesisInstalled)
			{
				Log.Log("BILLION NEMESIS is ACTIVE");
			}
			IsUltraStatsInstalled = Chainloader.PluginInfos.ContainsKey("atom.ultrastats");
			if (IsUltraStatsInstalled)
			{
				Log.Log("ULTRASTATS is ACTIVE");
			}
			IsStrayModeInstalled = Chainloader.PluginInfos.ContainsKey("plonk.straymode");
			if (IsStrayModeInstalled)
			{
				Log.Log("STRAYMODE is ACTIVE");
			}
			IsUltraskinsInstalled = Chainloader.PluginInfos.ContainsKey("ultrakill.UltraSkins.bobthecorn");
			if (IsUltraskinsInstalled)
			{
				Log.Log("ULTRASKINS_GC is ACTIVE");
			}
			IsTitleScreenQuickAccessInstalled = Chainloader.PluginInfos.ContainsKey("com.github.end-4.titleScreenQuickAccess");
			if (IsTitleScreenQuickAccessInstalled)
			{
				Log.Log("TITLE SCREEN QUICK ACCESS is ACTIVE");
			}
			foreach (string key in Chainloader.PluginInfos.Keys)
			{
				PluginInfo val = Chainloader.PluginInfos[key];
				string location = val.Location;
				string fileName = Path.GetFileName(location);
				location = location.Replace(fileName, "");
				if (Directory.Exists(location))
				{
					Log.LogDebug("FILE PATH: " + location + " \n EXISTS");
					string[] files = Directory.GetFiles(location, "*.json", SearchOption.AllDirectories);
					string[] array = files;
					foreach (string path in array)
					{
						JsonReader.RegisterFullPath(key, path);
					}
				}
			}
		}

		private void Update()
		{
		}

		private void SetIcon()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_006a: 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)
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string text = Path.Combine(directoryName, "icon.png");
			if (!string.IsNullOrEmpty(text))
			{
				byte[] array = File.ReadAllBytes(text);
				if (array.Length != 0)
				{
					Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
					ImageConversion.LoadImage(val, array);
					Sprite image = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
					config.image = image;
				}
			}
		}

		private void CreateConfig()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			config = PluginConfigurator.Create("Zephyr's Menu Cleaner", "net.zephyr.ultrakill.LayerConfigurator");
			SetIcon();
			IgnoreUnreleasedLevels = new BoolField(config.rootPanel, "Ignore RANKS from Unreleased Levels", "ignore_unreleased", false);
			ConfigPanel configLocationButton = new ConfigPanel(config.rootPanel, "Open CONFIG Folder", "feedback_button", (PanelFieldType)3);
			configLocationButton.onPannelOpenEvent += (OpenPanelEventDelegate)delegate
			{
				string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
				string text = Path.Combine(directoryName, "data/");
				Application.OpenURL(directoryName);
				configLocationButton.ClosePanel();
			};
			ConfigPanel feedbackButton = new ConfigPanel(config.rootPanel, "Send FEEDBACK / REPORT BUG (discord)", "feedback_button", (PanelFieldType)3);
			feedbackButton.onPannelOpenEvent += (OpenPanelEventDelegate)delegate
			{
				Process.Start("https://discord.gg/KcsjvKa6jw");
				feedbackButton.ClosePanel();
			};
		}

		private static Sprite SetUserIcon(Friend friend)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_000f: 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)
			//IL_0026: Expected O, but got Unknown
			//IL_0040: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject();
			RawImage val2 = val.AddComponent<RawImage>();
			SteamController.FetchAvatar(val2, friend);
			Texture2D val3 = FlipTexture((Texture2D)val2.texture);
			Sprite result = Sprite.Create(val3, new Rect(0f, 0f, (float)((Texture)val3).width, (float)((Texture)val3).height), Vector2.one * 0.5f);
			Object.Destroy((Object)(object)val);
			return result;
		}

		private static Texture2D FlipTexture(Texture2D original)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(((Texture)original).width, ((Texture)original).height);
			for (int i = 0; i < ((Texture)original).width; i++)
			{
				for (int j = 0; j < ((Texture)original).height; j++)
				{
					val.SetPixel(i, ((Texture)original).height - j - 1, original.GetPixel(i, j));
				}
			}
			val.Apply();
			return val;
		}
	}
}
namespace UltrakillLayerConfigurator.Scripts
{
	public class ChapterTitle : MonoBehaviour
	{
		public List<Button> buttons = new List<Button>();

		public ChapterTitle? previous;

		public string name;

		private ChapterTitle()
		{
			name = ((TMP_Text)((Component)((Component)this).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text;
		}

		private void OnEnable()
		{
			((TMP_Text)((Component)((Component)this).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = name;
			if (buttons.Count == 0 || !((Object)(object)previous != (Object)null))
			{
				return;
			}
			bool flag = true;
			foreach (Button button in previous.buttons)
			{
				if (((Component)button).gameObject.activeSelf)
				{
					flag = false;
				}
			}
			if (flag)
			{
				if (((TMP_Text)((Component)((Component)previous).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text.ToLower().Contains("secondary"))
				{
					((TMP_Text)((Component)((Component)this).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = ((TMP_Text)((Component)((Component)previous).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text;
				}
				((Component)previous).gameObject.SetActive(false);
			}
		}
	}
	[DefaultExecutionOrder(5000)]
	public class CustomMainMenuManager : MonoBehaviour
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__43_0;

			public static Func<Object, bool> <>9__51_0;

			internal void <SortChapters>b__43_0()
			{
				EventSystem.current.SetSelectedGameObject((GameObject)null);
			}

			internal bool <CreateScrollView>b__51_0(Object e)
			{
				return e.name == "Scrollbar (1)";
			}
		}

		private GameObject canvas;

		private GameObject saves;

		private GameObject gameController;

		private GameObject mainMenu;

		private GameObject difficultySelection;

		private GameObject chapterSelection;

		private GameObject chapters;

		private bool _updatedDifficulties = false;

		private bool _updatedChapters = false;

		private bool _updatedSaves = false;

		private bool _updatedLayers = false;

		private bool _updatedUltraskins = false;

		private bool _updatedStrayMode = false;

		private bool _openedDifficulties = false;

		private bool _openedChapters = false;

		private bool _openedSaves = false;

		private ScrollRect _difficultyRect;

		private static readonly Type PluginType = AccessTools.TypeByName("BillionNemesis.NemesisThorn");

		private static readonly Type ConfigurableType = AccessTools.TypeByName("ThornClient.Core.Configurable");

		private static readonly Dictionary<int, Sprite> PanelIconCache = new Dictionary<int, Sprite>();

		public static readonly Dictionary<int, string> NameCache = new Dictionary<int, string>();

		public static readonly Dictionary<ChapterSelectButton, Color> ChapterPRankColorCache = new Dictionary<ChapterSelectButton, Color>();

		public static readonly Dictionary<LayerSelect, Color> LayerPRankColorCache = new Dictionary<LayerSelect, Color>();

		public static readonly Dictionary<LevelSelectPanel, Color> LevelPRankColorCache = new Dictionary<LevelSelectPanel, Color>();

		public static readonly Dictionary<ChapterSelectButton, Color> ChapterBaseColorCache = new Dictionary<ChapterSelectButton, Color>();

		public static readonly Dictionary<LayerSelect, Color> LayerBaseColorCache = new Dictionary<LayerSelect, Color>();

		public static readonly Dictionary<LevelSelectPanel, Color> LevelBaseColorCache = new Dictionary<LevelSelectPanel, Color>();

		public static CustomMainMenuManager Instance { get; private set; }

		public static void Create()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			if (SceneHelper.IsSceneRankless && (!Object.op_Implicit((Object)(object)Instance) || Object.FindObjectsOfType<CustomMainMenuManager>().Length == 0))
			{
				GameObject val = new GameObject("CustomMainMenuManager");
				CustomMainMenuManager instance = val.AddComponent<CustomMainMenuManager>();
				Instance = instance;
			}
		}

		private async void Start()
		{
			LevelSelectPanel[] array = Object.FindObjectsByType<LevelSelectPanel>((FindObjectsInactive)1, (FindObjectsSortMode)1);
			foreach (LevelSelectPanel panel in array)
			{
				int num = panel.levelNumber;
				if (num == 100 || num == 666)
				{
					num += panel.levelNumberInLayer - 1;
				}
				PanelIconCache.TryAdd(num, ((Component)((Component)panel).transform.Find("Image")).GetComponent<Image>().sprite);
			}
			canvas = GameObject.Find("/Canvas");
			saves = ((Component)canvas.transform.Find("OptionsMenu").Find("Save Slots")).gameObject;
			gameController = GameObject.Find("GameController");
			JsonReader.ChapterNumber = 999;
		}

		private void LateUpdate()
		{
			if ((Object)(object)canvas != (Object)null)
			{
				TryRedoDifficulties();
				TryRedoChapters();
				RedoSaves();
				TryRedoMainMenu();
			}
		}

		private void TryRedoMainMenu()
		{
			if (!_updatedStrayMode && LayerPlugin.IsStrayModeInstalled && LayerPlugin.IsUltraStatsInstalled)
			{
				((MonoBehaviour)this).StartCoroutine(RedoStrayMode());
				_updatedStrayMode = true;
			}
			if (!_updatedUltraskins && LayerPlugin.IsUltraskinsInstalled)
			{
				((MonoBehaviour)this).StartCoroutine(RedoUltraSkins());
				_updatedUltraskins = true;
			}
		}

		private IEnumerator RedoStrayMode()
		{
			Stopwatch sw = Stopwatch.StartNew();
			LayerPlugin.Log.Log("Starting to move Straymode Button");
			Task<Transform> findTask = FindStraymodeButton();
			if (!findTask.IsCompleted)
			{
				yield return (object)new WaitUntil((Func<bool>)(() => findTask.IsCompleted));
			}
			Transform result = findTask.Result;
			RectTransform rect = ((Component)result).GetComponent<RectTransform>();
			float offset = 172.9219f;
			rect.offsetMin = new Vector2(rect.offsetMin.x, rect.offsetMin.y + offset);
			rect.offsetMax = new Vector2(rect.offsetMax.x, rect.offsetMax.y + offset);
			sw.Stop();
			LayerPlugin.Log.Log($"Moved Straymode Button after {sw.ElapsedMilliseconds} ms");
		}

		private async Task<Transform> FindStraymodeButton()
		{
			GameObject search;
			do
			{
				search = GameObject.Find("Straymode Site Links(Clone)");
				if ((Object)(object)search == (Object)null)
				{
					await Task.Delay(5);
				}
			}
			while ((Object)(object)search == (Object)null);
			Transform search2;
			do
			{
				search2 = search.transform.Find("STRAYMODE Collapsed");
				if ((Object)(object)search2 == (Object)null)
				{
					await Task.Delay(5);
				}
			}
			while ((Object)(object)search2 == (Object)null);
			return search2;
		}

		private IEnumerator RedoUltraSkins()
		{
			Stopwatch sw = Stopwatch.StartNew();
			Task<Transform> findTask = FindULTRASKINSButton();
			if (!findTask.IsCompleted)
			{
				yield return (object)new WaitUntil((Func<bool>)(() => findTask.IsCompleted));
			}
			Transform search = findTask.Result;
			search.localScale = Vector3.one;
			RectTransform rect = ((Component)search).GetComponent<RectTransform>();
			float offset = (LayerPlugin.IsTitleScreenQuickAccessInstalled ? 76 : 0);
			rect.offsetMin = new Vector2(offset + 376f, -315f);
			rect.offsetMax = new Vector2(offset + 446f, -245f);
			rect.pivot = new Vector2(0f, 1f);
			HudOpenEffect effect = ComponentExtensions.GetOrAddComponent<HudOpenEffect>((Component)(object)search);
			effect.originalSpeed = 30f;
			effect.speed = 30f;
			RectTransform imageRect = ((Component)search.GetChild(0)).GetComponent<RectTransform>();
			((Component)imageRect).transform.localScale = new Vector3(1.5f, 1.5f, 1f);
			imageRect.offsetMin = new Vector2(-22.5f, -22.5f);
			imageRect.offsetMax = new Vector2(22.5f, 22.5f);
			imageRect.anchorMin = new Vector2(0f, 1f);
			imageRect.anchorMax = new Vector2(0f, 1f);
			sw.Stop();
			LayerPlugin.Log.Log($"Moved ULTRASKINS Button in {sw.ElapsedMilliseconds} ms");
		}

		private async Task<Transform> FindULTRASKINSButton()
		{
			GameObject search;
			do
			{
				search = GameObject.Find("ultraskinsmenubutton(Clone)");
				if ((Object)(object)search == (Object)null)
				{
					await Task.Delay(5);
				}
			}
			while ((Object)(object)search == (Object)null);
			return search.transform;
		}

		private async void RedoLayers()
		{
			if (_updatedLayers || !Object.op_Implicit((Object)(object)chapterSelection))
			{
				return;
			}
			Transform parent = chapterSelection.transform.parent;
			Transform ChapterBaseTransform = parent.Find("Level Select (Act I)");
			if (!Object.op_Implicit((Object)(object)ChapterBaseTransform))
			{
				return;
			}
			Stopwatch sw = Stopwatch.StartNew();
			GameObject ChapterTemplate = Object.Instantiate<GameObject>(((Component)ChapterBaseTransform).gameObject, parent);
			((Object)ChapterTemplate).name = "Chapter";
			ScrollRect scroll = ChapterTemplate.GetComponentInChildren<ScrollRect>();
			GameObject layerTemplate = Object.Instantiate<GameObject>(((Component)((Component)scroll.content).transform.Find("Layer 1 Limbo")).gameObject, ((Component)scroll.content).transform);
			((Object)layerTemplate).name = "Layer";
			foreach (Transform item in ((Component)scroll.content).transform)
			{
				Transform child = item;
				if ((Object)(object)((Component)child).gameObject != (Object)(object)layerTemplate)
				{
					Object.Destroy((Object)(object)((Component)child).gameObject);
				}
			}
			GameObject levelRow = ((Component)layerTemplate.transform.Find("Level Row")).gameObject;
			GameObject levelTemplate = Object.Instantiate<GameObject>(((Component)levelRow.transform.GetChild(0)).gameObject, levelRow.transform);
			((Object)levelTemplate).name = "Level";
			foreach (Transform item2 in levelRow.transform)
			{
				Transform child2 = item2;
				if ((Object)(object)((Component)child2).gameObject != (Object)(object)levelTemplate)
				{
					Object.Destroy((Object)(object)((Component)child2).gameObject);
				}
			}
			_updatedLayers = true;
			await JsonReader.PopulateCategories();
			foreach (string category in JsonReader.ChapterCategoriesWithButtons.Keys)
			{
				for (int i = 0; i < JsonReader.ChapterCategoriesWithButtons[category].Count; i++)
				{
					Button b = JsonReader.ChapterCategoriesWithButtons[category][i];
					ChapterSelectButton chapSelect = ((Component)b).GetComponent<ChapterSelectButton>();
					if ((Object)(object)chapSelect == (Object)null)
					{
						continue;
					}
					string buttonName = ((TMP_Text)((Component)((Component)b).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text.ToLower();
					if (!JsonReader.ChapterDefinitions.ContainsKey(buttonName))
					{
						continue;
					}
					ChapterEntry entry = JsonReader.ChapterDefinitions[buttonName];
					ChapterBaseColorCache.Add(chapSelect, ChapterDatabase.ToColor(entry.DefaultColor));
					ChapterPRankColorCache.Add(chapSelect, ChapterDatabase.ToColor(entry.PrankColor));
					GameObject chapterBase = Object.Instantiate<GameObject>(((Component)ChapterBaseTransform).gameObject, parent);
					((Object)chapterBase).name = entry.Name;
					chapterBase.GetComponent<LevelSelectAct>();
					Button button = ((Component)chapSelect).GetComponent<Button>();
					button.onClick = new ButtonClickedEvent();
					((UnityEvent)button.onClick).AddListener((UnityAction)delegate
					{
						EventSystem.current.SetSelectedGameObject((GameObject)null);
						chapterSelection.SetActive(false);
						chapterBase.SetActive(true);
					});
					MenuActSelect menuActSelect = ((Component)chapSelect).GetComponent<MenuActSelect>();
					menuActSelect.nameWhenDisabled = entry.DisabledName;
					menuActSelect.requiredLevels = entry.RequiredLevels;
					menuActSelect.hideWhenOff = entry.HideWhenOff;
					menuActSelect.primeLevels = entry.PrimeLevels;
					menuActSelect.forceOff = entry.ForceOff;
					ScrollRect scrollRect = chapterBase.GetComponentInChildren<ScrollRect>();
					foreach (Transform item3 in ((Component)scrollRect.content).transform)
					{
						Transform child3 = item3;
						Object.Destroy((Object)(object)((Component)child3).gameObject);
					}
					List<LayerSelect> layers = new List<LayerSelect>();
					foreach (LayerEntry layer in entry.Layers)
					{
						GameObject layerObject = Object.Instantiate<GameObject>(layerTemplate, ((Component)scrollRect.content).transform);
						((Object)layerObject).name = layer.Name;
						LayerSelect l = layerObject.GetComponent<LayerSelect>();
						LayerBaseColorCache.Add(l, ChapterDatabase.ToColor(layer.DefaultColor));
						LayerPRankColorCache.Add(l, ChapterDatabase.ToColor(layer.PrankColor));
						layers.Add(l);
						l.layerNumber = layer.LayerNumber;
						l.levelAmount = layer.Missions.Count;
						LayerPlugin.Log.LogDebug(l.levelAmount + " levels in layer " + l.layerNumber);
						l.noSecretMission = layer.SecretMission.LevelNumber == -1;
						if (!l.noSecretMission)
						{
							l.secretMissionPanel.missionNumber = layer.SecretMission.LevelNumber;
						}
						Button secretLevelButton = ((Component)l.secretMissionPanel).GetComponent<Button>();
						secretLevelButton.onClick = new ButtonClickedEvent();
						((UnityEvent)secretLevelButton.onClick).AddListener((UnityAction)delegate
						{
							gameController.GetComponent<OptionsManager>().ChangeLevelAbrupt("Level " + layer.SecretMission.LeaderboardLevel);
						});
						GameObject Header = ((Component)layerObject.transform.GetChild(0)).gameObject;
						((TMP_Text)Header.GetComponentInChildren<TextMeshProUGUI>()).text = layer.Name;
						GameObject levels = ((Component)layerObject.transform.GetChild(1)).gameObject;
						foreach (Transform item4 in levels.transform)
						{
							Transform child4 = item4;
							Object.Destroy((Object)(object)((Component)child4).gameObject);
						}
						foreach (MissionEntry mission in layer.Missions)
						{
							GameObject levelObject = Object.Instantiate<GameObject>(levelTemplate, levels.transform);
							Button levelButton = levelObject.GetComponent<Button>();
							levelButton.onClick = new ButtonClickedEvent();
							((UnityEvent)levelButton.onClick).AddListener((UnityAction)delegate
							{
								gameController.GetComponent<OptionsManager>().ChangeLevelAbrupt("Level " + mission.LeaderboardLevel);
							});
							((Object)levelObject).name = mission.Name;
							LevelSelectPanel level = levelObject.GetComponent<LevelSelectPanel>();
							LevelBaseColorCache.Add(level, ChapterDatabase.ToColor(mission.DefaultColor));
							LevelPRankColorCache.Add(level, ChapterDatabase.ToColor(mission.PrankColor));
							level.levelNumberInLayer = layer.Missions.IndexOf(mission) + 1;
							level.levelNumber = mission.LevelNumber;
							if (mission.Name != "")
							{
								((TMP_Text)((Component)((Component)level).transform.Find("Name")).GetComponent<TextMeshProUGUI>()).text = mission.Name;
								NameCache[level.levelNumber] = mission.Name;
							}
							if (string.IsNullOrWhiteSpace(mission.UnlockedThumbnailPath))
							{
								int num = mission.LevelNumber;
								if (num == 100 || num == 666)
								{
									num += level.levelNumberInLayer - 1;
									((Component)level.challengeIcon).gameObject.SetActive(false);
									level.challengeIcon = null;
									RectTransform rank = ((Component)((Component)level).transform.Find("Stats").Find("Rank")).GetComponent<RectTransform>();
									rank.anchorMin = new Vector2(0.5f, 0f);
									rank.anchorMax = new Vector2(0.5f, 0f);
									rank.pivot = new Vector2(0.5f, 0.5f);
									rank.offsetMin = new Vector2(-30f, 10f);
									rank.offsetMax = new Vector2(30f, 70f);
								}
								((Component)((Component)level).transform.Find("Image")).GetComponent<Image>().sprite = PanelIconCache[num];
							}
							level.leaderboardPanel.GetComponent<LevelSelectLeaderboard>().layerLevelNumber = mission.LeaderboardLevel;
						}
					}
					chapSelect.layersInChapter = layers.ToArray();
					chapSelect.CheckScore();
					foreach (LayerSelect layer2 in layers)
					{
						LevelSelectPanel[] componentsInChildren = ((Component)layer2).GetComponentsInChildren<LevelSelectPanel>(true);
						LevelSelectPanel[] array = componentsInChildren;
						for (int num2 = 0; num2 < array.Length; num2++)
						{
							_ = array[num2];
						}
					}
				}
			}
			sw.Stop();
			LayerPlugin.Log.Log($"Loaded Layers in {sw.ElapsedMilliseconds} ms");
		}

		private async Task TryRedoChapters()
		{
			await Task.Delay(10);
			if (!_updatedChapters)
			{
				Transform search = canvas.transform.Find("Chapter Select");
				if (!((Object)(object)search == (Object)null))
				{
					chapterSelection = ((Component)search).gameObject;
					if (Object.op_Implicit((Object)(object)chapterSelection))
					{
						_updatedChapters = true;
						((MonoBehaviour)this).StartCoroutine(RedoChaptersCoroutine());
					}
				}
			}
			else if (Object.op_Implicit((Object)(object)chapterSelection) && Object.op_Implicit((Object)(object)chapters))
			{
				Button[] allChapters = chapters.GetComponentsInChildren<Button>(true);
				List<Button> allButtons = new List<Button>(allChapters);
				if (JsonReader.ChapterNumber != allButtons.Count && allButtons.Count != 0)
				{
					((MonoBehaviour)this).StartCoroutine(SortChaptersCoroutine(allButtons));
				}
			}
		}

		private IEnumerator SortChaptersCoroutine(List<Button> allButtons)
		{
			LayerPlugin.Log.LogDebug($"{JsonReader.ChapterNumber} != {allButtons.Count}");
			Task t1 = JsonReader.SortAllChapters(allButtons);
			if (!t1.IsCompleted)
			{
				yield return (object)new WaitUntil((Func<bool>)(() => t1.IsCompleted));
			}
			Task t2 = SortChapters(chapters);
			if (!t2.IsCompleted)
			{
				yield return (object)new WaitUntil((Func<bool>)(() => t2.IsCompleted));
			}
		}

		private IEnumerator RedoChaptersCoroutine()
		{
			Stopwatch sw = Stopwatch.StartNew();
			chapters = ((Component)chapterSelection.transform.Find("Chapters")).gameObject;
			Button[] allChapters = chapters.GetComponentsInChildren<Button>(true);
			List<Button> allButtons = new List<Button>(allChapters);
			if (allButtons.Count == 0)
			{
				yield break;
			}
			GameObject primary = ((Component)chapters.transform.Find("Primary")).gameObject;
			GameObject secondary = ((Component)chapters.transform.Find("Secondary")).gameObject;
			Object.Destroy((Object)(object)secondary);
			if (LayerPlugin.IsBillionNemesisInstalled)
			{
				GameObject DifficultyTitle = ((Component)chapterSelection.transform.Find("Title (2)")).gameObject;
				string text = ((TMP_Text)DifficultyTitle.GetComponent<TextMeshProUGUI>()).text;
				text = text.Replace("\n<color=#ff00af>(NEMESIS)</color>", "");
				((TMP_Text)DifficultyTitle.GetComponent<TextMeshProUGUI>()).text = text;
				GameObject preludeButtonOriginal = ((Component)chapters.transform.Find("Prelude")).gameObject;
				preludeButtonOriginal.GetComponent<ChapterSelectButton>();
				GameObject actIButtonOriginal = ((Component)chapters.transform.Find("Act I")).gameObject;
				actIButtonOriginal.GetComponent<ChapterSelectButton>();
				GameObject actIiButtonOriginal = ((Component)chapters.transform.Find("Act II")).gameObject;
				actIiButtonOriginal.GetComponent<ChapterSelectButton>();
				GameObject actIiiButtonOriginal = ((Component)chapters.transform.Find("Act III")).gameObject;
				actIiiButtonOriginal.GetComponent<ChapterSelectButton>();
				Type changedInfoType = AccessTools.TypeByName("BillionNemesis.ChangedInfo");
				if (changedInfoType != null)
				{
					object value = AccessTools.Field(changedInfoType, "ChangedLayers")?.GetValue(null);
					IEnumerable<string> changedLayers = value as IEnumerable<string>;
					if (changedLayers != null)
					{
						if (changedLayers.ToArray().Length != 0)
						{
							GameObject preludeButton = Object.Instantiate<GameObject>(preludeButtonOriginal, chapterSelection.transform);
							((TMP_Text)((Component)preludeButton.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = "<color=#ff00af>[NEMESIS]</color> PRELUDE";
							allButtons.Add(preludeButton.GetComponent<Button>());
						}
						if (changedLayers.ToArray().Length > 1)
						{
							GameObject actIButton = Object.Instantiate<GameObject>(actIButtonOriginal, chapterSelection.transform);
							((TMP_Text)((Component)actIButton.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = "<color=#ff00af>[NEMESIS]</color> ACT I";
							allButtons.Add(actIButton.GetComponent<Button>());
						}
						if (changedLayers.ToArray().Length > 4)
						{
							GameObject actIiButton = Object.Instantiate<GameObject>(actIiButtonOriginal, chapterSelection.transform);
							((TMP_Text)((Component)actIiButton.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = "<color=#ff00af>[NEMESIS]</color> ACT II";
							allButtons.Add(actIiButton.GetComponent<Button>());
						}
						if (changedLayers.ToArray().Length > 7)
						{
							GameObject actIiiButton = Object.Instantiate<GameObject>(actIiiButtonOriginal, chapterSelection.transform);
							((TMP_Text)((Component)actIiiButton.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = "<color=#ff00af>[NEMESIS]</color> ACT III";
							allButtons.Add(actIiiButton.GetComponent<Button>());
						}
					}
				}
			}
			LayerPlugin.Log.LogDebug("LOAD ALL CHAPTERS");
			Task loadChaptersTask = JsonReader.LoadAllChapters(allButtons);
			if (!loadChaptersTask.IsCompleted)
			{
				yield return (object)new WaitUntil((Func<bool>)(() => loadChaptersTask.IsCompleted));
			}
			LayerPlugin.Log.LogDebug($"CREATE TITLES [{JsonReader.ChapterCategoriesWithButtons.Keys.Count}]");
			ChapterTitle previousChapterTitle = null;
			foreach (string s in JsonReader.ChapterCategoriesWithButtons.Keys)
			{
				GameObject title = Object.Instantiate<GameObject>(primary, chapters.transform);
				title.transform.localScale = Vector3.one;
				((TMP_Text)((Component)title.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = s;
				ChapterTitle chapterTitle = title.AddComponent<ChapterTitle>();
				chapterTitle.buttons = JsonReader.ChapterCategoriesWithButtons[s];
				if (Object.op_Implicit((Object)(object)previousChapterTitle))
				{
					chapterTitle.previous = previousChapterTitle;
				}
				previousChapterTitle = chapterTitle;
			}
			Object.Destroy((Object)(object)primary);
			Task sortTask = SortChapters(chapters);
			if (!sortTask.IsCompleted)
			{
				yield return (object)new WaitUntil((Func<bool>)(() => sortTask.IsCompleted));
			}
			ScrollRect rect = DefineScrollingArea("Chapters", chapters.GetComponent<RectTransform>(), chapterSelection.transform, new ScrollViewParameters
			{
				scrollSensitivity = 5f,
				elasticity = 0.1f,
				preferredElementHeight = 54f,
				viewportAnchorMax = new Vector2(1f, 1f),
				viewportAnchorMin = new Vector2(0f, 0f),
				viewportOffsetMin = new Vector2(0f, 0f),
				viewportOffsetMax = new Vector2(0f, 0f),
				contentAnchorMax = new Vector2(1f, 1f),
				contentAnchorMin = new Vector2(0f, 0f),
				contentOffsetMin = new Vector2(0f, 0f),
				contentOffsetMax = new Vector2(0f, 0f),
				contentPivot = new Vector2(0.5f, 1f),
				anchorMax = new Vector2(1f, 1f),
				anchorMin = new Vector2(0f, 0f),
				pivot = new Vector2(0.5f, 0.5f),
				offsetMin = new Vector2(0f, 50f),
				offsetMax = new Vector2(0f, -140f),
				scrollbarPivot = new Vector2(0f, 0.5f),
				scrollbarAnchorMax = new Vector2(0.5f, 1f),
				scrollbarAnchorMin = new Vector2(0.5f, 0f),
				scrollbarOffsetMax = new Vector2(240f, 0f),
				scrollbarOffsetMin = new Vector2(220f, 0f)
			});
			rect.normalizedPosition = new Vector2(0f, 1f);
			sw.Stop();
			LayerPlugin.Log.Log($"Loaded Chapters in {sw.ElapsedMilliseconds} ms");
		}

		private async Task SortChapters(GameObject parent)
		{
			Dictionary<string, Transform> titles = new Dictionary<string, Transform>();
			List<Transform> buttons = new List<Transform>();
			for (int i = 0; i < parent.transform.childCount; i++)
			{
				Transform t = parent.transform.GetChild(i);
				if ((Object)(object)((Component)t).GetComponent<Button>() != (Object)null)
				{
					buttons.Add(t);
					continue;
				}
				string s = ((TMP_Text)((Component)t.GetChild(0)).GetComponent<TextMeshProUGUI>()).text;
				titles[s] = t;
			}
			if (buttons.Count == 0)
			{
				return;
			}
			LayerPlugin.Log.LogDebug("DETACH FROM [" + ((Object)parent).name + " (" + ((Object)parent.transform.parent).name + ")]");
			parent.transform.DetachChildren();
			for (int j = 0; j < JsonReader.ChapterCategoriesWithButtons.Keys.Count; j++)
			{
				string category = JsonReader.ChapterCategoriesWithButtons.Keys.ToArray()[j];
				if (!titles.ContainsKey(category))
				{
					continue;
				}
				titles[category].SetParent(parent.transform);
				LayerPlugin.Log.LogDebug("[" + category + "]");
				foreach (Button b in JsonReader.ChapterCategoriesWithButtons[category])
				{
					((Component)b).transform.SetParent(parent.transform);
					LayerPlugin.Log.LogDebug("[" + ((Object)b).name + "] attached to [" + ((Object)parent).name + "]");
					ButtonClickedEvent onClick = b.onClick;
					object obj = <>c.<>9__43_0;
					if (obj == null)
					{
						UnityAction val = delegate
						{
							EventSystem.current.SetSelectedGameObject((GameObject)null);
						};
						<>c.<>9__43_0 = val;
						obj = (object)val;
					}
					((UnityEvent)onClick).AddListener((UnityAction)obj);
					if (!LayerPlugin.IsBillionNemesisInstalled || !((TMP_Text)((Component)((Component)b).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text.ToLower().Contains("nemesis"))
					{
						continue;
					}
					((UnityEvent)b.onClick).AddListener((UnityAction)delegate
					{
						if (PluginType != null)
						{
							object obj2 = AccessTools.Field(PluginType, "Instance")?.GetValue(null);
							if (obj2 != null)
							{
								AccessTools.Field(ConfigurableType, "_isEnabled")?.SetValue(obj2, true);
							}
						}
						((Component)b).GetComponent<ChapterSelectButton>().CheckScore();
					});
				}
			}
			List<GameObject> toActivate = new List<GameObject>();
			for (int i2 = 0; i2 < parent.transform.childCount; i2++)
			{
				toActivate.Add(((Component)parent.transform.GetChild(i2)).gameObject);
			}
			parent.GetComponent<ObjectActivateInSequence>().objectsToActivate = toActivate.ToArray();
		}

		private async void RedoSaves()
		{
			if (!saves.activeSelf)
			{
				return;
			}
			await Task.Delay(50);
			if (_updatedSaves)
			{
				return;
			}
			Transform search = canvas.transform.Find("OptionsMenu");
			if ((Object)(object)search == (Object)null)
			{
				return;
			}
			GameObject saveSelection = ((Component)search).gameObject;
			if (!Object.op_Implicit((Object)(object)saveSelection))
			{
				return;
			}
			_updatedSaves = true;
			Stopwatch sw = Stopwatch.StartNew();
			GameObject slots = ((Component)saveSelection.transform.Find("Save Slots")).gameObject;
			GameObject grid = ((Component)slots.transform.Find("Grid")).gameObject;
			SlotRowPanel[] allSaveSlots = grid.GetComponentsInChildren<SlotRowPanel>(true);
			List<SlotRowPanel> allButtons = new List<SlotRowPanel>(allSaveSlots);
			LayerPlugin.Log.LogDebug("LOAD ALL SAVE SLOTS");
			await JsonReader.LoadAllSaves(allButtons);
			LayerPlugin.Log.LogDebug($"CREATE TITLES [{JsonReader.SavesCategoriesWithButtons.Keys.Count}]");
			GameObject titleTemplate = new GameObject("Title", new Type[1] { typeof(RectTransform) });
			GameObject titleText = new GameObject("Title Text", new Type[2]
			{
				typeof(TextMeshProUGUI),
				typeof(RectTransform)
			});
			titleTemplate.transform.SetParent(grid.transform);
			titleText.transform.SetParent(titleTemplate.transform);
			TextMeshProUGUI t = titleText.GetComponent<TextMeshProUGUI>();
			((TMP_Text)t).autoSizeTextContainer = false;
			((TMP_Text)t).font = ((TMP_Text)((Component)grid.transform.GetChild(0).Find("Slot Text")).GetComponent<TextMeshProUGUI>()).font;
			((TMP_Text)t).fontSize = 28f;
			((TMP_Text)t).alignment = (TextAlignmentOptions)514;
			((Graphic)t).color = new Color(1f, 1f, 1f, 1f);
			RectTransform titleRect = titleTemplate.GetComponent<RectTransform>();
			titleRect.anchorMin = new Vector2(0f, 0f);
			titleRect.anchorMax = new Vector2(1f, 1f);
			titleRect.offsetMin = new Vector2(0f, -37.5f);
			titleRect.offsetMax = new Vector2(0f, 37.5f);
			RectTransform textRect = titleText.GetComponent<RectTransform>();
			textRect.anchorMin = new Vector2(0f, 0f);
			textRect.anchorMax = new Vector2(1f, 1f);
			textRect.offsetMin = new Vector2(0f, 0f);
			textRect.offsetMax = new Vector2(0f, 0f);
			foreach (string s in JsonReader.SavesCategoriesWithButtons.Keys)
			{
				GameObject title = Object.Instantiate<GameObject>(titleTemplate, grid.transform);
				title.transform.localScale = Vector3.one;
				((TMP_Text)((Component)title.transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = s;
				LayerPlugin.Log.LogDebug("CREATE TITLES [" + s + "]");
			}
			Object.Destroy((Object)(object)titleTemplate);
			await SortSaves(grid);
			ScrollRect rect = DefineScrollingArea("Saves", grid.GetComponent<RectTransform>(), slots.transform, new ScrollViewParameters
			{
				scrollSensitivity = 5f,
				elasticity = 0.1f,
				preferredElementHeight = 61.2604f,
				viewportAnchorMax = new Vector2(1f, 1f),
				viewportAnchorMin = new Vector2(0f, 0f),
				viewportOffsetMin = new Vector2(0f, 0f),
				viewportOffsetMax = new Vector2(0f, 0f),
				contentAnchorMax = new Vector2(1f, 1f),
				contentAnchorMin = new Vector2(0f, 0f),
				contentOffsetMin = new Vector2(30f, 0f),
				contentOffsetMax = new Vector2(-30f, 0f),
				contentPivot = new Vector2(0.5f, 0.5f),
				anchorMax = new Vector2(1f, 0.5f),
				anchorMin = new Vector2(0f, 0.5f),
				pivot = new Vector2(0.5f, 0.5f),
				offsetMin = new Vector2(130f, -250f),
				offsetMax = new Vector2(-130f, 250f),
				scrollbarOffsetMin = new Vector2(-30f, 0f),
				scrollbarOffsetMax = new Vector2(0f, 0f)
			});
			rect.normalizedPosition = new Vector2(0f, 1f);
			slots.transform.GetChild(slots.transform.childCount - 1).SetAsFirstSibling();
			sw.Stop();
			LayerPlugin.Log.Log($"Loaded Saves in {sw.ElapsedMilliseconds} ms");
		}

		private async Task SortSaves(GameObject parent)
		{
			Dictionary<string, Transform> titles = new Dictionary<string, Transform>();
			List<Transform> buttons = new List<Transform>();
			for (int i = 0; i < parent.transform.childCount; i++)
			{
				Transform t = parent.transform.GetChild(i);
				if ((Object)(object)((Component)t).GetComponent<Image>() != (Object)null)
				{
					buttons.Add(t);
					continue;
				}
				string s = ((TMP_Text)((Component)t.GetChild(0)).GetComponent<TextMeshProUGUI>()).text;
				LayerPlugin.Log.LogDebug("SORTING TITLE " + s);
				if (!string.IsNullOrEmpty(s))
				{
					titles[s] = t;
				}
			}
			if (buttons.Count == 0)
			{
				return;
			}
			LayerPlugin.Log.LogDebug("DETACH FROM [" + ((Object)parent).name + " (" + ((Object)parent.transform.parent).name + ")]");
			parent.transform.DetachChildren();
			LayerPlugin.Log.LogDebug($"{JsonReader.SavesCategoriesWithButtons.Keys.Count} ");
			for (int j = 0; j < JsonReader.SavesCategoriesWithButtons.Keys.Count; j++)
			{
				string category = JsonReader.SavesCategoriesWithButtons.Keys.ToArray()[j];
				if (!titles.ContainsKey(category))
				{
					continue;
				}
				titles[category].SetParent(parent.transform);
				string s2 = ((TMP_Text)((Component)titles[category].GetChild(0)).GetComponent<TextMeshProUGUI>()).text;
				((TMP_Text)((Component)((Component)titles[category]).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text = "-- " + s2 + " --";
				LayerPlugin.Log.LogDebug("[" + category + "]");
				foreach (SlotRowPanel b in JsonReader.SavesCategoriesWithButtons[category])
				{
					((Component)b).transform.SetParent(parent.transform);
				}
			}
		}

		private void TryRedoDifficulties()
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			if (!_updatedDifficulties)
			{
				Transform val = canvas.transform.Find("Difficulty Select (1)");
				if (!((Object)(object)val == (Object)null))
				{
					difficultySelection = ((Component)val).gameObject;
					if (Object.op_Implicit((Object)(object)difficultySelection))
					{
						_updatedDifficulties = true;
						((MonoBehaviour)this).StartCoroutine(RedoDifficulties());
					}
				}
			}
			else if (Object.op_Implicit((Object)(object)difficultySelection) && Object.op_Implicit((Object)(object)_difficultyRect) && _openedDifficulties != difficultySelection.activeSelf)
			{
				_openedDifficulties = difficultySelection.activeSelf;
				_difficultyRect.normalizedPosition = new Vector2(0f, 1f);
			}
		}

		private IEnumerator RedoDifficulties()
		{
			Stopwatch sw = Stopwatch.StartNew();
			GameObject interactables = ((Component)difficultySelection.transform.Find("Interactables")).gameObject;
			ObjectActivateInSequence seq = interactables.GetComponent<ObjectActivateInSequence>();
			DifficultySelectButton[] allDifficulties = (DifficultySelectButton[])(object)Object.FindObjectsOfType(typeof(DifficultySelectButton), true);
			Task loadDifficultiesTask = JsonReader.LoadAllDifficulties(allDifficulties);
			if (!loadDifficultiesTask.IsCompleted)
			{
				yield return null;
			}
			List<GameObject> objectsToActivate = new List<GameObject>();
			GameObject title = ((Component)interactables.transform.Find("Title")).gameObject;
			GameObject tip = ((Component)interactables.transform.Find("Assist Tip")).gameObject;
			objectsToActivate.Add(title);
			_difficultyRect = DefineScrollingArea("Difficulty", interactables.transform, new ScrollViewParameters
			{
				scrollSensitivity = 5f,
				elasticity = 0.1f,
				viewportAnchorMax = new Vector2(1f, 1f),
				viewportAnchorMin = new Vector2(0f, 0f),
				viewportOffsetMin = new Vector2(0f, 0f),
				viewportOffsetMax = new Vector2(0f, 0f),
				contentAnchorMax = new Vector2(1f, 1f),
				contentAnchorMin = new Vector2(0f, 0f),
				contentOffsetMin = new Vector2(24.85f, 0f),
				contentOffsetMax = new Vector2(0f, 0f),
				contentPivot = new Vector2(0.5f, 1f),
				anchorMax = new Vector2(0f, 1f),
				anchorMin = new Vector2(0f, 0f),
				pivot = new Vector2(0f, 0.5f),
				offsetMin = new Vector2(0f, 50f),
				offsetMax = new Vector2(842f, -100f),
				scrollbarOffsetMin = new Vector2(-420f, 0f),
				scrollbarOffsetMax = new Vector2(-400f, 0f),
				spacing = 50f
			});
			DifficultyMenuCategoryObject difObj = new DifficultyMenuCategoryObject(interactables);
			for (int i = 0; i < JsonReader.DifficultyCategoriesWithButtons.Keys.Count; i++)
			{
				string category = JsonReader.DifficultyCategoriesWithButtons.Keys.ToArray()[i];
				GameObject t = difObj.CreateNew(ref objectsToActivate, category, JsonReader.DifficultyCategoriesWithButtons[category]);
				t.transform.SetParent((Transform)(object)_difficultyRect.content);
				t.transform.localScale = new Vector3(1f, 1f, 1f);
				RectTransform component = t.GetComponent<RectTransform>();
				component.offsetMax += new Vector2(0f, 100f);
			}
			difObj.Destroy();
			LayerPlugin.Log.Log(allDifficulties.Length + " DIFFICULTIES FOUND!");
			objectsToActivate.Add(tip);
			GameObject[] objectsToActivate2 = seq.objectsToActivate;
			foreach (GameObject go in objectsToActivate2)
			{
				if (!objectsToActivate.Contains(go))
				{
					Object.Destroy((Object)(object)go);
				}
			}
			seq.objectsToActivate = objectsToActivate.ToArray();
			LayoutRebuilder.ForceRebuildLayoutImmediate(_difficultyRect.content);
			_difficultyRect.normalizedPosition = new Vector2(0f, 1f);
			if (LayerPlugin.Instance.IgnoreUnreleasedLevels.value)
			{
				DifficultySelectButton[] array = Object.FindObjectsByType<DifficultySelectButton>((FindObjectsInactive)1, (FindObjectsSortMode)1);
				foreach (DifficultySelectButton e in array)
				{
					((MonoBehaviour)this).StartCoroutine(ComponentExtensions.GetOrAddComponent<DifficultySelectScoreButton>((Component)(object)e).GetCache());
				}
			}
			sw.Stop();
			LayerPlugin.Log.Log($"Loaded Difficulties in {sw.ElapsedMilliseconds} ms");
		}

		public static ScrollRect DefineScrollingArea(string name, Transform parent, ScrollViewParameters parameters)
		{
			ScrollRect scrollRect = CreateScrollView(name, parent);
			return CreateScrollingArea(scrollRect, parameters);
		}

		public static ScrollRect DefineScrollingArea(string name, RectTransform content, Transform parent, ScrollViewParameters parameters)
		{
			ScrollRect val = CreateScrollView(name, parent);
			val.content = content;
			((Component)val.content).transform.SetParent(((Component)val.viewport).transform, false);
			ContentSizeFitter val2 = ((Component)val.content).gameObject.AddComponent<ContentSizeFitter>();
			val2.verticalFit = (FitMode)2;
			return CreateScrollingArea(val, parameters);
		}

		private static ScrollRect CreateScrollingArea(ScrollRect scrollRect, ScrollViewParameters parameters)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: 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_01d9: Unknown result type (might be due to invalid IL or missing references)
			if (parameters.preferredElementHeight != 0f)
			{
				for (int i = 0; i < ((Transform)scrollRect.content).childCount; i++)
				{
					GameObject gameObject = ((Component)((Component)scrollRect.content).transform.GetChild(i)).gameObject;
					LayoutElement val = gameObject.AddComponent<LayoutElement>();
					val.preferredHeight = parameters.preferredElementHeight;
				}
			}
			scrollRect.scrollSensitivity = parameters.scrollSensitivity;
			scrollRect.elasticity = parameters.elasticity;
			scrollRect.viewport.anchorMin = parameters.viewportAnchorMin;
			scrollRect.viewport.anchorMax = parameters.viewportAnchorMax;
			scrollRect.viewport.offsetMin = parameters.viewportOffsetMin;
			scrollRect.viewport.offsetMax = parameters.viewportOffsetMax;
			scrollRect.content.anchorMin = parameters.contentAnchorMin;
			scrollRect.content.anchorMax = parameters.contentAnchorMax;
			scrollRect.content.offsetMin = parameters.contentOffsetMin;
			scrollRect.content.offsetMax = parameters.contentOffsetMax;
			scrollRect.content.pivot = parameters.contentPivot;
			RectTransform component = ((Component)scrollRect).GetComponent<RectTransform>();
			component.anchorMax = parameters.anchorMax;
			component.anchorMin = parameters.anchorMin;
			component.pivot = parameters.pivot;
			component.offsetMin = parameters.offsetMin;
			component.offsetMax = parameters.offsetMax;
			RectTransform component2 = ((Component)scrollRect.verticalScrollbar).GetComponent<RectTransform>();
			if (parameters.scrollbarAnchorMin != Vector2.zero || parameters.scrollbarAnchorMax != Vector2.zero)
			{
				component2.anchorMin = parameters.scrollbarAnchorMin;
				component2.anchorMax = parameters.scrollbarAnchorMax;
			}
			if (parameters.scrollbarPivot != Vector2.zero)
			{
				component2.pivot = parameters.scrollbarPivot;
			}
			component2.offsetMin = parameters.scrollbarOffsetMin;
			component2.offsetMax = parameters.scrollbarOffsetMax;
			VerticalLayoutGroup component3 = ((Component)scrollRect.content).GetComponent<VerticalLayoutGroup>();
			if (parameters.spacing >= 0f)
			{
				((HorizontalOrVerticalLayoutGroup)component3).spacing = parameters.spacing;
			}
			return scrollRect;
		}

		public static ScrollRect CreateScrollView(string name, Transform parent)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			GameObject val = new GameObject(name + " Scroll View", new Type[4]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Mask),
				typeof(ScrollRect)
			});
			val.transform.SetParent(parent, false);
			((Graphic)val.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.05f);
			ScrollRect component = val.GetComponent<ScrollRect>();
			GameObject val2 = new GameObject("Viewport", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Mask)
			});
			val2.transform.SetParent(val.transform, false);
			((Graphic)val2.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.05f);
			Mask component2 = val2.GetComponent<Mask>();
			component2.showMaskGraphic = false;
			GameObject val3 = new GameObject("Content", new Type[1] { typeof(RectTransform) });
			val3.transform.SetParent(val2.transform, false);
			VerticalLayoutGroup val4 = val3.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)val4).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)val4).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)val4).spacing = 0f;
			((LayoutGroup)val4).padding.top = 0;
			((LayoutGroup)val4).padding.bottom = 0;
			((LayoutGroup)val4).padding.left = 2;
			((LayoutGroup)val4).padding.right = 2;
			((LayoutGroup)val4).childAlignment = (TextAnchor)0;
			ContentSizeFitter val5 = val3.AddComponent<ContentSizeFitter>();
			val5.verticalFit = (FitMode)2;
			Object? obj = (from e in Object.FindObjectsOfType(typeof(Scrollbar), true)
				where e.name == "Scrollbar (1)"
				select e).FirstOrDefault();
			Scrollbar val6 = (Scrollbar)(object)((obj is Scrollbar) ? obj : null);
			if (!Object.op_Implicit((Object)(object)((Component)val6).gameObject))
			{
				LayerPlugin.Log.Error("NO SCROLLBAR FOUND");
			}
			GameObject val7 = Object.Instantiate<GameObject>(((Component)val6).gameObject);
			val7.transform.SetParent(val.transform, false);
			Scrollbar component3 = val7.GetComponent<Scrollbar>();
			component3.direction = (Direction)2;
			component.viewport = val2.GetComponent<RectTransform>();
			component.content = val3.GetComponent<RectTransform>();
			component.verticalScrollbar = component3;
			component.vertical = true;
			component.horizontal = false;
			component.verticalScrollbarVisibility = (ScrollbarVisibility)2;
			component.movementType = (MovementType)2;
			component.elasticity = 0f;
			return component;
		}
	}
	[DefaultExecutionOrder(5000)]
	public class DifficultySelectScoreButton : MonoBehaviour
	{
		public struct RankCache
		{
			public int totalScore;

			public bool notComplete;

			public int golds;

			public int allPerfects;

			public int length;
		}

		public Text rankText;

		private Image buttonBg;

		private Sprite originalSprite;

		[SerializeField]
		private static Sprite buttonOnP;

		private Image rankButton;

		private Sprite originalRankSprite;

		private DifficultySelectButton selectButton;

		private TextMeshProUGUI progress;

		[SerializeField]
		private static Sprite rankOnP;

		private ChapterSelectButton[] allChapters;

		private Dictionary<ChapterSelectButton, RankCache> allChaptersCache = new Dictionary<ChapterSelectButton, RankCache>();

		private RankCache cache;

		private static readonly FieldRef<ChapterSelectButton, Sprite> RankOnPRef = AccessTools.FieldRefAccess<ChapterSelectButton, Sprite>("rankOnP");

		private static readonly FieldRef<ChapterSelectButton, Sprite> OriginalSpriteRef = AccessTools.FieldRefAccess<ChapterSelectButton, Sprite>("originalSprite");

		private static readonly FieldRef<ChapterSelectButton, Sprite> OriginalRankSpriteRef = AccessTools.FieldRefAccess<ChapterSelectButton, Sprite>("originalRankSprite");

		private static readonly FieldRef<ChapterSelectButton, Image> ButtonBgRef = AccessTools.FieldRefAccess<ChapterSelectButton, Image>("buttonBg");

		private static readonly FieldRef<ChapterSelectButton, Image> RankButtonRef = AccessTools.FieldRefAccess<ChapterSelectButton, Image>("rankButton");

		private static readonly FieldRef<ChapterSelectButton, Sprite> ButtonOnPRef = AccessTools.FieldRefAccess<ChapterSelectButton, Sprite>("buttonOnP");

		private void Awake()
		{
			Setup();
		}

		private void Setup()
		{
			buttonBg = ((Component)this).GetComponent<Image>();
			buttonBg.fillCenter = true;
			originalSprite = buttonBg.sprite;
			rankText = ((Component)((Component)this).transform.Find("RankPanel")).GetComponentInChildren<Text>();
			rankButton = ((Component)((Component)rankText).transform.parent).GetComponent<Image>();
			originalRankSprite = rankButton.sprite;
			selectButton = ((Component)this).GetComponent<DifficultySelectButton>();
			allChapters = Object.FindObjectsByType<ChapterSelectButton>((FindObjectsInactive)1, (FindObjectsSortMode)1);
			progress = ((Component)((Component)this).transform.Find("Progress")).GetComponent<TextMeshProUGUI>();
		}

		private void OnEnable()
		{
			((MonoBehaviour)this).StartCoroutine(CheckScore());
		}

		private void OnDisable()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (((Selectable)((Component)this).GetComponent<Button>()).interactable)
			{
				((Graphic)buttonBg).color = Color.white;
				buttonBg.sprite = originalSprite;
				rankText.text = "";
				((Graphic)rankButton).color = Color.white;
				rankButton.sprite = originalRankSprite;
			}
		}

		private RankCache CheckChaptersCache()
		{
			LayerPlugin.Log.LogDebug("CREATE");
			RankCache result = default(RankCache);
			LayerPlugin.Log.LogDebug("get icons");
			if ((Object)(object)rankOnP == (Object)null)
			{
				rankOnP = RankOnPRef.Invoke(allChapters.First());
			}
			if ((Object)(object)buttonOnP == (Object)null)
			{
				buttonOnP = ButtonOnPRef.Invoke(allChapters.First());
			}
			ChapterSelectButton[] array = allChapters;
			foreach (ChapterSelectButton val in array)
			{
				LayerPlugin.Log.LogDebug("chapter " + ((Object)val).name);
				MonoSingleton<PrefsManager>.Instance.SetInt("difficulty", selectButton.difficulty);
				LayerPlugin.Log.LogDebug($"chapter dictionary exists for difficulty {selectButton.difficulty}? {allChaptersCache.ContainsKey(val)}");
				if (!allChaptersCache.ContainsKey(val))
				{
					ButtonBgRef.Invoke(val) = ((Component)val).GetComponent<Image>();
					ButtonBgRef.Invoke(val).sprite = originalSprite;
					OriginalSpriteRef.Invoke(val) = ButtonBgRef.Invoke(val).sprite;
					RankButtonRef.Invoke(val) = ((Component)val.rankText.transform.parent).GetComponent<Image>();
					RankButtonRef.Invoke(val).sprite = originalRankSprite;
					OriginalRankSpriteRef.Invoke(val) = RankButtonRef.Invoke(val).sprite;
					try
					{
						val.CheckScore();
					}
					catch (Exception ex)
					{
						LayerPlugin.Log.Warn(ex.Message);
					}
					ButtonBgRef.Invoke(val).sprite = OriginalSpriteRef.Invoke(val);
					RankButtonRef.Invoke(val).sprite = OriginalRankSpriteRef.Invoke(val);
					LayerPlugin.Log.LogDebug("create chapter cache");
					RankCache value = new RankCache
					{
						totalScore = val.totalScore,
						notComplete = val.notComplete,
						allPerfects = val.allPerfects,
						golds = val.golds,
						length = val.layersInChapter.Length
					};
					LayerPlugin.Log.LogDebug("adding to main dictionary");
					allChaptersCache[val] = value;
				}
				LayerPlugin.Log.LogDebug("get");
				RankCache rankCache = allChaptersCache[val];
				LayerPlugin.Log.LogDebug("set");
				result.totalScore += rankCache.totalScore;
				if (rankCache.notComplete)
				{
					result.notComplete = true;
				}
				if (rankCache.allPerfects == rankCache.length)
				{
					result.allPerfects++;
				}
				if (rankCache.golds == rankCache.length)
				{
					result.golds++;
				}
			}
			result.length = allChapters.Length;
			return result;
		}

		public IEnumerator GetCache()
		{
			Stopwatch sw = Stopwatch.StartNew();
			LayerPlugin.Log.WriteLine("Creating cache for " + ((Object)this).name.ToUpper() + "...", ConsoleColor.DarkYellow);
			if (LayerPlugin.Instance.IgnoreUnreleasedLevels.value)
			{
				Setup();
				if ((Object)(object)buttonBg == (Object)null)
				{
					buttonBg = ((Component)this).GetComponent<Image>();
				}
				((Graphic)buttonBg).color = Color.white;
				buttonBg.sprite = originalSprite;
				cache = CheckChaptersCache();
				sw.Stop();
				LayerPlugin.Log.Log($"Created cache for {((Object)this).name.ToUpper()} [difficulty: {selectButton.difficulty}] in {sw.ElapsedMilliseconds}ms");
			}
			yield break;
		}

		public IEnumerator CheckScore()
		{
			Stopwatch sw = Stopwatch.StartNew();
			if (!LayerPlugin.Instance.IgnoreUnreleasedLevels.value)
			{
				sw.Stop();
				yield break;
			}
			LayerPlugin.Log.WriteLine("Fetching cache for " + ((Object)this).name.ToUpper() + "...", ConsoleColor.DarkYellow);
			if (!((Selectable)((Component)this).GetComponent<Button>()).interactable)
			{
				sw.Stop();
				LogEnd(sw.ElapsedMilliseconds, "Unreleased");
				yield break;
			}
			if (cache.length == 0)
			{
				yield return GetCache();
			}
			if (cache.notComplete)
			{
				sw.Stop();
				LogEnd(sw.ElapsedMilliseconds, "Incomplete");
				yield break;
			}
			if (cache.allPerfects == cache.length)
			{
				rankText.text = "<color=#FFFFFF>P</color>";
				((Graphic)rankButton).color = new Color(1f, 0.686f, 0f, 1f);
				rankButton.sprite = rankOnP;
				if (cache.golds == cache.length)
				{
					((Graphic)buttonBg).color = new Color(1f, 0.686f, 0f, 1f);
					buttonBg.sprite = buttonOnP;
					((TMP_Text)progress).text = "<color=#FFFFFF>" + ((TMP_Text)progress).text + "</color>";
					sw.Stop();
					LogEnd(sw.ElapsedMilliseconds, "GOLD");
				}
				else
				{
					sw.Stop();
					LogEnd(sw.ElapsedMilliseconds, "PERFECT");
				}
				yield break;
			}
			int totalScore = cache.totalScore / cache.length;
			switch (totalScore)
			{
			case 1:
				rankText.text = "<color=#4CFF00>C</color>";
				break;
			case 2:
				rankText.text = "<color=#FFD800>B</color>";
				break;
			case 3:
				rankText.text = "<color=#FF6A00>A</color>";
				break;
			case 4:
			case 5:
			case 6:
			case 7:
			case 8:
			case 9:
				rankText.text = "<color=#FF0000>S</color>";
				break;
			default:
				rankText.text = "<color=#0094FF>D</color>";
				break;
			}
			((Graphic)rankButton).color = Color.white;
			rankButton.sprite = originalRankSprite;
			sw.Stop();
			LogEnd(sw.ElapsedMilliseconds, $"{totalScore} score out of {cache.length} chapters");
		}

		private void LogEnd(long time, string result)
		{
			LayerPlugin.Log.Log($"Loaded {((Object)this).name.ToUpper()} [difficulty: {selectButton.difficulty}] in {time}ms ({result})");
		}
	}
	public class LayerCreator
	{
	}
}
namespace UltrakillLayerConfigurator.Data
{
	public class DifficultyMenuCategoryObject
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__6_0;

			internal void <CreateNew>b__6_0()
			{
				EventSystem.current.SetSelectedGameObject((GameObject)null);
			}
		}

		private GameObject template;

		public GameObject Parent;

		public Transform Name;

		public Transform Line1;

		public Transform Line2;

		public DifficultyMenuCategoryObject(GameObject parent)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			Parent = parent;
			template = new GameObject("Category Template", new Type[4]
			{
				typeof(RectTransform),
				typeof(LayoutElement),
				typeof(Image),
				typeof(VerticalLayoutGroup)
			});
			template.transform.parent = Parent.transform;
			template.transform.localScale = new Vector3(1f, 1f, 1f);
			RectTransform component = template.GetComponent<RectTransform>();
			RectTransform component2 = Parent.GetComponent<RectTransform>();
			VerticalLayoutGroup component3 = template.GetComponent<VerticalLayoutGroup>();
			((LayoutGroup)component3).childAlignment = (TextAnchor)6;
			((HorizontalOrVerticalLayoutGroup)component3).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)component3).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)component3).childControlWidth = false;
			((HorizontalOrVerticalLayoutGroup)component3).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)component3).spacing = 4f;
			Image component4 = template.GetComponent<Image>();
			((Graphic)component4).color = Color.clear;
			component.sizeDelta = component2.sizeDelta;
			component.anchorMax = component2.anchorMax;
			component.anchorMin = component2.anchorMin;
			component.pivot = component2.pivot;
			Name = Object.Instantiate<Transform>(parent.transform.Find("Easy"), template.transform);
			((Object)Name).name = "Category Title";
			Line1 = Object.Instantiate<Transform>(parent.transform.Find("LineBreak (1)"), template.transform);
			((Object)Line1).name = "LineBreak 1";
			Line2 = Object.Instantiate<Transform>(parent.transform.Find("LineBreak (3)"), template.transform);
			((Object)Line2).name = "LineBreak 2";
			template.transform.localScale = new Vector3(1f, 1f, 1f);
		}

		public GameObject CreateNew(ref List<GameObject> toAppear, string category, List<DifficultySelectButton> buttons)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: 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_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Expected O, but got Unknown
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)template == (Object)null)
			{
				LayerPlugin.Log.Error("Missing Template");
				return null;
			}
			if (buttons.Count == 0)
			{
				return null;
			}
			int num = 0;
			template.transform.localScale = new Vector3(1f, 1f, 1f);
			GameObject val = Object.Instantiate<GameObject>(template);
			((Object)val).name = "Category (" + category.ToLower() + ")";
			val.transform.localScale = new Vector3(1f, 1f, 1f);
			float num2 = 55f * ((float)buttons.Count / 2f) - 25f;
			Transform val2 = val.transform.Find("Category Title");
			if ((Object)(object)val2 == (Object)null)
			{
				LayerPlugin.Log.Error("Missing Category Title");
				return val;
			}
			val2.localPosition = new Vector3(17f, num2 + 50f, 0f);
			val2.localScale = new Vector3(1f, 1f, 1f);
			TextMeshProUGUI component = ((Component)val2).GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).text = category;
			Transform val3 = val.transform.Find("LineBreak 1");
			if ((Object)(object)val3 == (Object)null)
			{
				LayerPlugin.Log.Error("Missing LineBreak 1");
				return val;
			}
			val3.localPosition = new Vector3(0f, num2 + 30f, 0f);
			val3.localScale = new Vector3(1f, 1f, 1f);
			for (int i = 0; i < buttons.Count; i++)
			{
				DifficultySelectButton val4 = buttons[i];
				if (!((Object)(object)val4 == (Object)null))
				{
					((Component)val4).transform.SetParent(val.transform);
					((Component)val4).transform.localScale = new Vector3(1f, 1f, 1f);
				}
			}
			Transform val5 = val.transform.Find("LineBreak 2");
			Transform val6 = Object.Instantiate<Transform>(val5, val5.parent);
			((Component)val6).gameObject.SetActive(((Component)val5).gameObject.activeSelf);
			Object.Destroy((Object)(object)((Component)val5).gameObject);
			if ((Object)(object)val6 == (Object)null)
			{
				LayerPlugin.Log.Error("Missing LineBreak 2");
				return val;
			}
			val6.localScale = new Vector3(1f, 1f, 1f);
			toAppear.Add(((Component)val2).gameObject);
			toAppear.Add(((Component)val3).gameObject);
			foreach (DifficultySelectButton button in buttons)
			{
				toAppear.Add(((Component)button).gameObject);
				((Component)button).gameObject.SetActive(false);
				ButtonClickedEvent onClick = ((Component)button).GetComponent<Button>().onClick;
				object obj = <>c.<>9__6_0;
				if (obj == null)
				{
					UnityAction val7 = delegate
					{
						EventSystem.current.SetSelectedGameObject((GameObject)null);
					};
					<>c.<>9__6_0 = val7;
					obj = (object)val7;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj);
				DifficultySelectScoreButton orAddComponent = ComponentExtensions.GetOrAddComponent<DifficultySelectScoreButton>((Component)(object)button);
			}
			toAppear.Add(((Component)val6).gameObject);
			val.transform.localScale = new Vector3(1f, 1f, 1f);
			return val;
		}

		public void Destroy()
		{
			Object.Destroy((Object)(object)template);
		}
	}
	[Serializable]
	public class EntryCategory
	{
		public string name;

		public List<string> entries;
	}
	public class EntryDatabase
	{
		public List<EntryCategory> categories;
	}
	public static class JsonReader
	{
		public const string DifficultyTag = "difficulties";

		public const string ChapterTag = "chapters";

		public const string LayerTag = "layers";

		public const string SavesTag = "saveslots";

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

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

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

		public static Dictionary<string, List<SlotRowPanel>> SavesCategoriesWithButtons = new Dictionary<string, List<SlotRowPanel>>();

		public static Dictionary<string, List<Button>> ChapterCategoriesWithButtons = new Dictionary<string, List<Button>>();

		public static Dictionary<string, List<DifficultySelectButton>> DifficultyCategoriesWithButtons = new Dictionary<string, List<DifficultySelectButton>>();

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

		public static int ChapterNumber = 999;

		public static int SavesNumber = 999;

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

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

		public static async Task LoadAllChapters(List<Button> buttons)
		{
			await ClearChapterCheck();
			if (ChapterCategories.Count == 0)
			{
				if (FirstPaths.ContainsKey("chapters"))
				{
					foreach (string path in FirstPaths["chapters"])
					{
						ChapterCategories = await Load(path, ChapterCategories);
					}
				}
				if (RegisteredPaths.ContainsKey("chapters"))
				{
					foreach (string path2 in RegisteredPaths["chapters"])
					{
						ChapterCategories = await Load(path2, ChapterCategories);
					}
				}
			}
			int totalChapters = 0;
			foreach (KeyValuePair<string, List<string>> chapterCategory in ChapterCategories)
			{
				totalChapters += chapterCategory.Value.Count;
			}
			LayerPlugin.Log.LogDebug($"{ChapterCategories.Keys.Count} CATEGORIES and {totalChapters} CHAPTERS FOUND IN JSONS!");
			await SortAllChapters(buttons);
		}

		public static async Task SortAllChapters(List<Button> buttons)
		{
			List<Button> chapters = new List<Button>(buttons);
			LayerPlugin.Log.LogDebug($"SORTING {chapters.Count} BUTTONS");
			if (ChapterNumber == chapters.Count || chapters.Count == 0)
			{
				return;
			}
			ChapterNumber = chapters.Count;
			ChapterCategoriesWithButtons.Clear();
			LayerPlugin.Log.LogDebug($"SORTING {buttons.Count} BUTTONS into {ChapterCategories.Keys.Count} CHAPTERS");
			foreach (string category in ChapterCategories.Keys)
			{
				foreach (string entry in ChapterCategories[category])
				{
					List<Button> chaptersToSort = new List<Button>(buttons);
					foreach (Button button in buttons)
					{
						string name = ((TMP_Text)((Component)((Component)button).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text.ToLower();
						if (name == entry.ToLower())
						{
							chapters.Remove(button);
							chaptersToSort.Remove(button);
							LayerPlugin.Log.LogDebug("Placing Button " + name + " into " + category);
							DictionaryCollectionExtensions.Add<string, List<Button>, Button>(ChapterCategoriesWithButtons, category, button);
							break;
						}
					}
					foreach (Button button2 in chaptersToSort)
					{
						string name2 = ((TMP_Text)((Component)((Component)button2).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text.ToLower();
						if (name2.Contains(entry.ToLower()))
						{
							chapters.Remove(button2);
							LayerPlugin.Log.LogDebug("Placing Button " + name2 + " into " + category);
							DictionaryCollectionExtensions.Add<string, List<Button>, Button>(ChapterCategoriesWithButtons, category, button2);
							break;
						}
					}
				}
			}
			if (chapters.Count > 0)
			{
				foreach (Button button3 in chapters)
				{
					DictionaryCollectionExtensions.Add<string, List<Button>, Button>(ChapterCategoriesWithButtons, "OTHER", button3);
				}
			}
			LayerPlugin.Log.LogDebug("SORTED ALL CHAPTERS");
		}

		public static async Task LoadAllSaves(List<SlotRowPanel> buttons)
		{
			await ClearChapterCheck();
			if (SavesCategories.Count == 0)
			{
				if (FirstPaths.ContainsKey("saveslots"))
				{
					foreach (string path in FirstPaths["saveslots"])
					{
						SavesCategories = await Load(path, SavesCategories);
					}
				}
				if (RegisteredPaths.ContainsKey("saveslots"))
				{
					foreach (string path2 in RegisteredPaths["saveslots"])
					{
						SavesCategories = await Load(path2, SavesCategories);
					}
				}
			}
			int totalSaves = 0;
			foreach (KeyValuePair<string, List<string>> savesCategory in SavesCategories)
			{
				totalSaves += savesCategory.Value.Count;
			}
			LayerPlugin.Log.LogDebug($"{SavesCategories.Keys.Count} CATEGORIES and {totalSaves} SAVES FOUND IN JSONS!");
			await SortAllSaves(buttons);
		}

		public static async Task SortAllSaves(List<SlotRowPanel> buttons)
		{
			LayerPlugin.Log.LogDebug("SORTING SAVES");
			List<SlotRowPanel> saves = new List<SlotRowPanel>(buttons);
			LayerPlugin.Log.LogDebug($"SORTING {saves.Count} BUTTONS");
			if (SavesNumber == saves.Count || saves.Count == 0)
			{
				return;
			}
			SavesNumber = saves.Count;
			SavesCategoriesWithButtons.Clear();
			LayerPlugin.Log.LogDebug($"SORTING {buttons.Count} BUTTONS into {SavesCategories.Keys.Count} SAVES");
			foreach (string category in SavesCategories.Keys)
			{
				foreach (string entry in SavesCategories[category])
				{
					List<SlotRowPanel> savesToSort = new List<SlotRowPanel>(buttons);
					foreach (SlotRowPanel button in buttons)
					{
						string name = ((TMP_Text)((Component)((Component)button).transform.Find("Slot Text")).GetComponent<TextMeshProUGUI>()).text.ToLower();
						if (name == entry.ToLower())
						{
							saves.Remove(button);
							savesToSort.Remove(button);
							LayerPlugin.Log.LogDebug("Placing Button " + name + " into " + category);
							DictionaryCollectionExtensions.Add<string, List<SlotRowPanel>, SlotRowPanel>(SavesCategoriesWithButtons, category, button);
							break;
						}
					}
					foreach (SlotRowPanel button2 in savesToSort)
					{
						string name2 = ((TMP_Text)((Component)((Component)button2).transform.Find("Slot Text")).GetComponent<TextMeshProUGUI>()).text.ToLower();
						if (name2.Contains(entry.ToLower()))
						{
							saves.Remove(button2);
							LayerPlugin.Log.LogDebug("Placing Button " + name2 + " into " + category);
							DictionaryCollectionExtensions.Add<string, List<SlotRowPanel>, SlotRowPanel>(SavesCategoriesWithButtons, category, button2);
							break;
						}
					}
				}
			}
			if (saves.Count > 0)
			{
				foreach (SlotRowPanel button3 in saves)
				{
					DictionaryCollectionExtensions.Add<string, List<SlotRowPanel>, SlotRowPanel>(SavesCategoriesWithButtons, "EXTRA", button3);
				}
			}
			LayerPlugin.Log.LogDebug("SORTED ALL SAVES");
		}

		public static async Task PopulateCategories()
		{
			if (ChapterDefinitions.Count != 0)
			{
				return;
			}
			if (FirstPaths.ContainsKey("layers"))
			{
				foreach (string path in FirstPaths["layers"])
				{
					ChapterDefinitions = await LoadLayers(path, ChapterDefinitions);
				}
			}
			if (!RegisteredPaths.ContainsKey("layers"))
			{
				return;
			}
			foreach (string path2 in RegisteredPaths["layers"])
			{
				ChapterDefinitions = await LoadLayers(path2, ChapterDefinitions);
			}
		}

		public static async Task ClearDifficultyCheck()
		{
			foreach (string category in DifficultyCategoriesWithButtons.Keys)
			{
				for (int i = 0; i < DifficultyCategoriesWithButtons[category].Count; i++)
				{
					if ((Object)(object)DifficultyCategoriesWithButtons[category][i] == (Object)null)
					{
						DifficultyCategoriesWithButtons.Clear();
						return;
					}
				}
			}
		}

		public static async Task ClearChapterCheck()
		{
			foreach (string category in ChapterCategoriesWithButtons.Keys)
			{
				for (int i = 0; i < ChapterCategoriesWithButtons[category].Count; i++)
				{
					if ((Object)(object)ChapterCategoriesWithButtons[category][i] == (Object)null)
					{
						ChapterCategoriesWithButtons.Clear();
						return;
					}
				}
			}
		}

		public static async Task LoadAllDifficulties(DifficultySelectButton[] allDifficulties)
		{
			List<DifficultySelectButton> difficulties = new List<DifficultySelectButton>(allDifficulties);
			await ClearDifficultyCheck();
			if (DifficultyCategories.Count == 0)
			{
				if (FirstPaths.ContainsKey("difficulties"))
				{
					foreach (string path in FirstPaths["difficulties"])
					{
						DifficultyCategories = await Load(path, DifficultyCategories);
					}
				}
				if (RegisteredPaths.ContainsKey("difficulties"))
				{
					foreach (string path2 in RegisteredPaths["difficulties"])
					{
						DifficultyCategories = await Load(path2, DifficultyCategories);
					}
				}
			}
			if (DifficultyCategoriesWithButtons.Count != 0)
			{
				return;
			}
			foreach (string category in DifficultyCategories.Keys)
			{
				foreach (string entry in DifficultyCategories[category])
				{
					List<DifficultySelectButton> difficultiesToSort = new List<DifficultySelectButton>(allDifficulties);
					foreach (DifficultySelectButton button in allDifficulties)
					{
						string name = ((TMP_Text)((Component)((Component)button).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text.ToLower();
						if (name == entry.ToLower())
						{
							difficulties.Remove(button);
							difficultiesToSort.Remove(button);
							DictionaryCollectionExtensions.Add<string, List<DifficultySelectButton>, DifficultySelectButton>(DifficultyCategoriesWithButtons, category, button);
						}
					}
					foreach (DifficultySelectButton button2 in difficultiesToSort)
					{
						string name2 = ((TMP_Text)((Component)((Component)button2).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text.ToLower();
						if (name2.Contains(entry.ToLower()))
						{
							difficulties.Remove(button2);
							DictionaryCollectionExtensions.Add<string, List<DifficultySelectButton>, DifficultySelectButton>(DifficultyCategoriesWithButtons, category, button2);
						}
					}
				}
			}
			if (difficulties.Count <= 0)
			{
				return;
			}
			foreach (DifficultySelectButton button3 in difficulties)
			{
				DictionaryCollectionExtensions.Add<string, List<DifficultySelectButton>, DifficultySelectButton>(DifficultyCategoriesWithButtons, "EXTRA", button3);
			}
		}

		public static async Task<Dictionary<string, List<string>>> Load(string path, Dictionary<string, List<string>> categories)
		{
			if (!File.Exists(path))
			{
				LayerPlugin.Log.Error("JSON file not found: " + path);
				return categories;
			}
			string json = File.ReadAllText(path);
			EntryDatabase db = JsonConvert.DeserializeObject<EntryDatabase>(json);
			if (db != null)
			{
				foreach (EntryCategory category in db.categories)
				{
					if (categories.ContainsKey(category.name))
					{
						categories[category.name].AddRange(category.entries);
					}
					else
					{
						categories.Add(category.name, category.entries);
					}
					LayerPlugin.Log.LogDebug($"Writing {category.entries.Count} ENTRIES into {category.name} [{categories[category.name].Count}]");
				}
			}
			return categories;
		}

		public static async Task<Dictionary<string, ChapterEntry>> LoadLayers(string path, Dictionary<string, ChapterEntry> chapters)
		{
			if (!File.Exists(path))
			{
				LayerPlugin.Log.Error("JSON file not found: " + path);
				return chapters;
			}
			string json = File.ReadAllText(path);
			ChapterDatabase db = JsonConvert.DeserializeObject<ChapterDatabase>(json);
			if (db != null)
			{
				foreach (ChapterEntry chapter in db.Chapters)
				{
					chapters.Add(chapter.Name.ToLower(), chapter);
				}
			}
			return chapters;
		}

		public static void RegisterDifficultyPath(string path)
		{
			RegisterPath("difficulties", path);
		}

		public static void RegisterChapterPath(string path)
		{
			RegisterPath("chapters", path);
		}

		public static void RegisterLayerPath(string path)
		{
			RegisterPath("layers", path);
		}

		public static void RegisterPath(string key, string path)
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			string text = Path.Combine(directoryName, "data/" + path + "." + key + ".json");
			if (!File.Exists(text))
			{
				LayerPlugin.Log.Warn("JSON file not found: " + text);
				text = Path.Combine(directoryName, path + "." + key + ".json");
			}
			if (text.Contains("LayerConfigurator"))
			{
				if (FirstPaths == null)
				{
					FirstPaths = new Dictionary<string, List<string>>();
				}
				DictionaryCollectionExtensions.Add<string, List<string>, string>(FirstPaths, key, path);
			}
			else
			{
				if (RegisteredPaths == null)
				{
					RegisteredPaths = new Dictionary<string, List<string>>();
				}
				DictionaryCollectionExtensions.Add<string, List<string>, string>(RegisteredPaths, key, text);
			}
		}

		public static void RegisterFullPath(string mod, string path)
		{
			string text;
			if (path.Contains("difficulties.json"))
			{
				text = "difficulties";
			}
			else if (path.Contains("chapters.json"))
			{
				text = "chapters";
			}
			else if (path.Contains("layers.json"))
			{
				text = "layers";
			}
			else
			{
				if (!path.Contains("saveslots.json"))
				{
					return;
				}
				text = "saveslots";
			}
			bool flag = false;
			if (mod == "net.zephyr.ultrakill.LayerConfigurator")
			{
				if (FirstPaths == null)
				{
					FirstPaths = new Dictionary<string, List<string>>();
				}
				DictionaryCollectionExtensions.Add<string, List<string>, string>(FirstPaths, text, path);
				flag = true;
			}
			else
			{
				if (RegisteredPaths == null)
				{
					RegisteredPaths = new Dictionary<string, List<string>>();
				}
				DictionaryCollectionExtensions.Add<string, List<string>, string>(RegisteredPaths, text, path);
			}
			string fileName = Path.GetFileName(path);
			if (flag)
			{
				LayerPlugin.Log.Log("Loaded [" + fileName + "]");
				return;
			}
			LayerPlugin.Log.Log("Loaded [" + fileName + "] (" + mod + ")");
		}
	}
	public struct ScrollViewParameters
	{
		public float spacing;

		public float elasticity;

		public float scrollSensitivity;

		public float preferredElementHeight;

		public Vector2 viewportAnchorMin;

		public Vector2 viewportAnchorMax;

		public Vector2 viewportOffsetMin;

		public Vector2 viewportOffsetMax;

		public Vector2 contentAnchorMin;

		public Vector2 contentAnchorMax;

		public Vector2 contentOffsetMin;

		public Vector2 contentOffsetMax;

		public Vector2 contentPivot;

		public Vector2 anchorMin;

		public Vector2 anchorMax;

		public Vector2 offsetMin;

		public Vector2 offsetMax;

		public Vector2 pivot;

		public Vector2 scrollbarOffsetMin;

		public Vector2 scrollbarOffsetMax;

		public Vector2 scrollbarAnchorMin;

		public Vector2 scrollbarAnchorMax;

		public Vector2 scrollbarPivot;

		public ScrollViewParameters()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			spacing = -1f;
			elasticity = 0.1f;
			scrollSensitivity = 5f;
			preferredElementHeight = 0f;
			viewportAnchorMin = new Vector2(0f, 0f);
			viewportAnchorMax = new Vector2(1f, 1f);
			viewportOffsetMin = new Vector2(0f, 0f);
			viewportOffsetMax = new Vector2(0f, 0f);
			contentAnchorMin = new Vector2(0f, 0f);
			contentAnchorMax = new Vector2(1f, 1f);
			contentOffsetMin = new Vector2(0f, 0f);
			contentOffsetMax = new Vector2(0f, 0f);
			contentPivot = new Vector2(0.5f, 0.5f);
			anchorMin = new Vector2(0f, 0f);
			anchorMax = new Vector2(1f, 1f);
			offsetMin = new Vector2(0f, 0f);
			offsetMax = new Vector2(0f, 0f);
			pivot = new Vector2(0.5f, 0.5f);
			scrollbarOffsetMin = new Vector2(0f, 0f);
			scrollbarOffsetMax = new Vector2(20f, 0f);
			scrollbarAnchorMin = new Vector2(0f, 0f);
			scrollbarAnchorMax = new Vector2(0f, 0f);
			scrollbarPivot = new Vector2(0f, 0f);
		}
	}
}
namespace UltrakillLayerConfigurator.Data.Layers
{
	public class ChapterDatabase
	{
		[JsonProperty("chapters")]
		public List<ChapterEntry> Chapters { get; set; } = new List<ChapterEntry>();

		public static Color ToColor(float[] colors)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			return new Color(colors[0], colors[1], colors[2], colors[3]);
		}
	}
	public class ChapterEntry
	{
		[JsonProperty("default_color")]
		public float[] DefaultColor = new float[4] { 1f, 1f, 1f, 1f };

		[JsonProperty("prank_color")]
		public float[] PrankColor = new float[4] { 1f, 0.686f, 0f, 1f };

		[JsonProperty("hide_when_off")]
		public bool HideWhenOff = false;

		[JsonProperty("prime_levels")]
		public bool PrimeLevels = false;

		[JsonProperty("force_off")]
		public bool ForceOff = false;

		[JsonProperty("name")]
		public string Name { get; set; }

		[JsonProperty("name_when_disabled")]
		public string DisabledName { get; set; }

		[JsonProperty("required_levels")]
		public int RequiredLevels { get; set; }

		[JsonProperty("layers")]
		public List<LayerEntry> Layers { get; set; } = new List<LayerEntry>();
	}
	public class LayerEntry
	{
		[JsonProperty("default_color")]
		public float[] DefaultColor = new float[4] { 0f, 0f, 0f, 0.35f };

		[JsonProperty("prank_color")]
		public float[] PrankColor = new float[4] { 1f, 0.686f, 0f, 1f };

		[JsonProperty("name")]
		public string Name { get; set; }

		[JsonProperty("layer_number")]
		public int LayerNumber { get; set; }

		[JsonProperty("missions")]
		public List<MissionEntry> Missions { get; set; } = new List<MissionEntry>();

		[JsonProperty("secret_mission")]
		public MissionEntry SecretMission { get; set; }
	}
	public class MissionEntry
	{
		[JsonProperty("name")]
		public string Name = "";

		[JsonProperty("name_when_disabled")]
		public string DisabledName = "";

		[JsonProperty("unlocked_thumbnail_path")]
		public string UnlockedThumbnailPath = "";

		[JsonProperty("locked_thumbnail_path")]
		public string LockedThumbnailPath = "";

		[JsonProperty("default_color")]
		public float[] DefaultColor = new float[4] { 0f, 0f, 0f, 0.35f };

		[JsonProperty("prank_color")]
		public float[] PrankColor = new float[4] { 1f, 0.686f, 0f, 1f };

		[JsonProperty("force_off")]
		public bool ForceOff = false;

		[JsonProperty("level_number")]
		public int LevelNumber { get; set; }

		[JsonProperty("leaderboard_level")]
		public string LeaderboardLevel { get; set; }
	}
}
namespace UltrakillLayerConfigurator.Patches
{
	[HarmonyPatch]
	public class BillionRankStuffPatch
	{
		private static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("BillionNemesis.RankStuff");
			if (type == null)
			{
				return null;
			}
			return AccessTools.Method(type, "UpdateRanksAndColors", (Type[])null, (Type[])null);
		}

		private static bool Prefix()
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(ChapterSelectButton))]
	public class ChapterSelectButtonPatch
	{
		private static readonly Type PluginType = AccessTools.TypeByName("BillionNemesis.NemesisThorn");

		private static readonly Type ConfigurableType = AccessTools.TypeByName("ThornClient.Core.Configurable");

		private static readonly FieldRef<ChapterSelectButton, Sprite> OriginalSpriteRef = AccessTools.FieldRefAccess<ChapterSelectButton, Sprite>("originalSprite");

		private static readonly FieldRef<ChapterSelectButton, Sprite> OriginalRankSpriteRef = AccessTools.FieldRefAccess<ChapterSelectButton, Sprite>("originalRankSprite");

		private static readonly FieldRef<ChapterSelectButton, Sprite> PRankButtonBgRef = AccessTools.FieldRefAccess<ChapterSelectButton, Sprite>("buttonOnP");

		private static readonly FieldRef<ChapterSelectButton, Sprite> PRankRankButtonRef = AccessTools.FieldRefAccess<ChapterSelectButton, Sprite>("rankOnP");

		private static readonly FieldRef<ChapterSelectButton, Image> ButtonBgRef = AccessTools.FieldRefAccess<ChapterSelectButton, Image>("buttonBg");

		private static readonly FieldRef<ChapterSelectButton, Image> RankButtonRef = AccessTools.FieldRefAccess<ChapterSelectButton, Image>("rankButton");

		private static bool switchedLast = false;

		[HarmonyPostfix]
		[HarmonyPatch("CheckScore")]
		public static void CheckScorePostfix(ChapterSelectButton __instance)
		{
			if (__instance.golds != __instance.layersInChapter.Length)
			{
				ButtonBgRef.Invoke(__instance).sprite = OriginalSpriteRef.Invoke(__instance);
			}
			if (__instance.allPerfects != __instance.layersInChapter.Length)
			{
				RankButtonRef.Invoke(__instance).sprite = OriginalRankSpriteRef.Invoke(__instance);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("CheckScore")]
		public static void CheckScorePrefix(ChapterSelectButton __instance)
		{
			ButtonBgRef.Invoke(__instance).sprite = OriginalSpriteRef.Invoke(__instance);
			RankButtonRef.Invoke(__instance).sprite = OriginalRankSpriteRef.Invoke(__instance);
			if (LayerPlugin.IsBillionNemesisInstalled)
			{
				Type type = AccessTools.TypeByName("BillionNemesis.NemesisThorn");
				if (type != null)
				{
					AccessTools.Field(type, "Instance");
				}
				if (PluginType != null)
				{
					object obj = AccessTools.Field(PluginType, "Instance")?.GetValue(null);
					if (obj != null)
					{
						FieldInfo fieldInfo = AccessTools.Field(ConfigurableType, "_isEnabled");
						bool flag = ((TMP_Text)((Component)((Component)__instance).transform.GetChild(0)).GetComponent<TextMeshProUGUI>()).text.ToLower().Contains("nemesis");
						if (switchedLast != flag)
						{
							switchedLast = flag;
							fieldInfo?.SetValue(obj, switchedLast);
						}
					}
				}
			}
			ButtonBgRef.Invoke(__instance).sprite = OriginalSpriteRef.Invoke(__instance);
			RankButtonRef.Invoke(__instance).sprite = OriginalRankSpriteRef.Invoke(__instance);
		}
	}
	[HarmonyPatch(typeof(DifficultySelectButton))]
	public class DifficultySelectButtonPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		public static void StartPostfix(DifficultySelectButton __instance)
		{
		}
	}
	[HarmonyPatch(typeof(GearCheckEnabler))]
	public static class GearCheckEnablerPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		public static void StartPostfix()
		{
			CustomMainMenuManager.Create();
		}
	}
	[HarmonyPatch(typeof(GetMissionName))]
	public class GetMissionNamePatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("GetMission")]
		public static bool GetMissionPrefix(int missionNum, ref string __result)
		{
			LayerPlugin.Log.LogDebug("HEELLLOOOOO");
			if (CustomMainMenuManager.NameCache.ContainsKey(missionNum))
			{
				LayerPlugin.Log.LogDebug(CustomMainMenuManager.NameCache[missionNum]);
				__result = CustomMainMenuManager.NameCache[missionNum];
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(LayerSelect))]
	public class LayerSelectPatch
	{
		private static readonly FieldRef<LayerSelect, float> TotalScoreRef = AccessTools.FieldRefAccess<LayerSelect, float>("totalScore");

		private static readonly FieldRef<LayerSelect, int> PerfectsRef = AccessTools.FieldRefAccess<LayerSelect, int>("perfects");

		private static readonly FieldRef<LayerSelect, bool> SecretMissionRef = AccessTools.FieldRefAccess<LayerSelect, bool>("secretMission");

		[HarmonyPostfix]
		[HarmonyPatch("CheckScore")]
		public static void CheckScorePostfix(LayerSelect __instance)
		{
			if (!LayerPlugin.Instance.IgnoreUnreleasedLevels.value)
			{
				return;
			}
			__instance.complete = true;
			int num = 0;
			LevelSelectPanel[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<LevelSelectPanel>(true);
			bool flag = false;
			LevelSelectPanel[] array = componentsInChildren;
			foreach (LevelSelectPanel val in array)
			{
				TextMeshProUGUI component = ((Component)((Component)val).transform.Find("Name")).GetComponent<TextMeshProUGUI>();
				if (val.forceOff || ((TMP_Text)component).text.Contains("P-3"))
				{
					flag = true;
				}
				RankData rank = GameProgressSaver.GetRank(val.levelNumber, false);
				int num2 = MonoSingleton<PrefsManager>.Instance.GetInt("difficulty", 0);
				if (flag && (val.forceOff || (Object.op_Implicit((Object)(object)component) && ((TMP_Text)component).text.Contains("???"))))
				{
					num++;
					__instance.golds++;
				}
				else if (rank == null || rank.ranks[num2] < 0)
				{
					__instance.complete = false;
					__instance.allPerfects = false;
					__instance.golds = 0;
					__instance.trueScore = 0;
					return;
				}
			}
			int num3 = __instance.levelAmount - num;
			if (num3 == 0)
			{
				__instance.trueScore = 4;
			}
			else
			{
				__instance.trueScore = Mathf.RoundToInt(TotalScoreRef.Invoke(__instance) / (float)num3);
			}
			if (PerfectsRef.Invoke(__instance) != num3)
			{
				return;
			}
			__instance.allPerfects = true;
			if (__instance.golds == __instance.levelAmount && __instance.levelAmount != 0)
			{
				if (Object.op_Implicit((Object)(object)__instance.secretMissionPanel) && __instance.secretMissionPanel.missionNumber == 8)
				{
					SecretMissionRef.Invoke(__instance) = true;
				}
				if (!Object.op_Implicit((Object)(object)__instance.secretMissionPanel) || __instance.noSecretMission || SecretMissionRef.Invoke(__instance))
				{
					__instance.gold = true;
				}
			}
		}
	}
}