Decompiled source of BetterQueue v1.3.4

plugins/BetterQueue/BetterQueue.dll

Decompiled 4 hours 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.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HG;
using Microsoft.CodeAnalysis;
using On.RoR2;
using On.RoR2.UI;
using RoR2;
using RoR2.Artifacts;
using RoR2.UI;
using RoR2.UI.SkinControllers;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BetterQueue
{
	[BepInPlugin("modwright.betterqueue", "Better Queue", "1.3.4")]
	public sealed class BetterQueuePlugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_OnDisplayBegin <0>__Display;

			public static hook_HandlePickupMessage <1>__Collected;
		}

		internal static BetterQueuePlugin Instance;

		internal PlanStore Store;

		internal SurvivorPlan Selected;

		internal readonly RunPlan Live = new RunPlan();

		internal ConfigEntry<bool> AutoSelect;

		internal ConfigEntry<bool> Preview;

		private ConfigEntry<KeyboardShortcut> editorKey;

		private float nextAttach;

		private float nextImport;

		private bool imported;

		private bool runStarted;

		private bool runBodyBound;

		private bool enabledHooks;

		private QueueOverlay overlay;

		private string storeProfile;

		private static readonly FieldInfo displayInventory = typeof(ItemInventoryDisplay).GetField("inventory", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo inventoryChanged = typeof(ItemInventoryDisplay).GetMethod("OnInventoryChanged", BindingFlags.Instance | BindingFlags.NonPublic);

		internal event Action Changed;

		private void Awake()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			AutoSelect = ((BaseUnityPlugin)this).Config.Bind<bool>("Queue", "AutoSelect", true, "Automatically select planned permanent items from Command cubes.");
			Preview = ((BaseUnityPlugin)this).Config.Bind<bool>("Interface", "ShowPreview", true, "Show the queue editor inside the native Tab scoreboard, using its existing blur and player list.");
			editorKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Interface", "EditorKey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Optional shortcut to toggle the native scoreboard with its queue editor. Tab follows the game's own binding.");
		}

		private void OnEnable()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			if (!enabledHooks)
			{
				enabledHooks = true;
				Run.onRunStartGlobal += StartRun;
				Run.onRunDestroyGlobal += EndRun;
				Stage.onStageStartGlobal += StageStarted;
				object obj = <>O.<0>__Display;
				if (obj == null)
				{
					hook_OnDisplayBegin val = CommandChoice.Display;
					<>O.<0>__Display = val;
					obj = (object)val;
				}
				PickupPickerController.OnDisplayBegin += (hook_OnDisplayBegin)obj;
				object obj2 = <>O.<1>__Collected;
				if (obj2 == null)
				{
					hook_HandlePickupMessage val2 = CommandChoice.Collected;
					<>O.<1>__Collected = val2;
					obj2 = (object)val2;
				}
				GenericPickupController.HandlePickupMessage += (hook_HandlePickupMessage)obj2;
				ItemInventoryDisplay.OnInventoryChanged += new hook_OnInventoryChanged(SafeInventoryChanged);
			}
		}

		private void SafeInventoryChanged(orig_OnInventoryChanged orig, ItemInventoryDisplay display)
		{
			if (!Object.op_Implicit((Object)(object)display))
			{
				if (display != null && displayInventory != null && inventoryChanged != null)
				{
					object? value = displayInventory.GetValue(display);
					Inventory val = (Inventory)((value is Inventory) ? value : null);
					if (Object.op_Implicit((Object)(object)val))
					{
						val.onInventoryChanged -= (Action)Delegate.CreateDelegate(typeof(Action), display, inventoryChanged);
					}
				}
			}
			else
			{
				orig.Invoke(display);
			}
		}

		private void Update()
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			ItemBrowser.Initialize();
			if (!ItemBrowser.Ready || !EnsureStore())
			{
				return;
			}
			if (!imported && Time.unscaledTime >= nextImport)
			{
				nextImport = Time.unscaledTime + 10f;
				Store.ImportLegacy(Paths.ConfigPath);
				imported = Store.Document.legacyImported;
			}
			if (Object.op_Implicit((Object)(object)Run.instance) && !runStarted)
			{
				StartRun(Run.instance);
			}
			if (!Object.op_Implicit((Object)(object)Run.instance) || !runBodyBound || Selected == null)
			{
				SelectSurvivor();
			}
			Store.Tick();
			if (Time.unscaledTime >= nextAttach)
			{
				nextAttach = Time.unscaledTime + 1f;
				if (!Object.op_Implicit((Object)(object)Run.instance))
				{
					LobbyTab.Attach();
				}
				if (!Object.op_Implicit((Object)(object)overlay))
				{
					overlay = ((Component)this).gameObject.AddComponent<QueueOverlay>();
				}
			}
			if (Object.op_Implicit((Object)(object)Run.instance))
			{
				KeyboardShortcut value = editorKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					overlay?.Toggle();
				}
			}
		}

		private bool EnsureStore()
		{
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			string text = ((firstLocalUser != null) ? firstLocalUser.userProfile : null)?.fileName;
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			if (Store != null && storeProfile == text)
			{
				return true;
			}
			Store?.Flush();
			Store = new PlanStore(Paths.ConfigPath, PlanSaveLocation.DirectoryFor(text));
			storeProfile = text;
			Selected = null;
			imported = false;
			nextImport = 0f;
			Live.Start(new SurvivorPlan());
			return true;
		}

		internal void SelectSurvivor()
		{
			//IL_0086: 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)
			if (!EnsureStore())
			{
				return;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
			if (Object.op_Implicit((Object)(object)Run.instance) && (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)firstLocalUser.cachedMaster) || (Object)(object)val.master != (Object)(object)firstLocalUser.cachedMaster))
			{
				return;
			}
			GameObject val2 = (Object.op_Implicit((Object)(object)Run.instance) ? BodyCatalog.GetBodyPrefab(val.bodyIndex) : (Object.op_Implicit((Object)(object)((firstLocalUser != null) ? firstLocalUser.currentNetworkUser : null)) ? BodyCatalog.GetBodyPrefab(firstLocalUser.currentNetworkUser.bodyIndexPreference) : null));
			if (Object.op_Implicit((Object)(object)Run.instance) && Object.op_Implicit((Object)(object)val2))
			{
				runBodyBound = true;
			}
			if (!Object.op_Implicit((Object)(object)val2) || Selected?.body == ((Object)val2).name)
			{
				return;
			}
			Store.Flush();
			Selected = Store.Get(((Object)val2).name);
			foreach (PlanEntry entry in Selected.entries)
			{
				string text = ItemBrowser.TierOf(entry.item);
				if (text != "Missing")
				{
					entry.tier = text;
				}
			}
			if (Object.op_Implicit((Object)(object)Run.instance))
			{
				Live.Start(Selected);
			}
			this.Changed?.Invoke();
		}

		private void StartRun(Run run)
		{
			if (EnsureStore())
			{
				Store.Flush();
				runStarted = true;
				runBodyBound = false;
				SelectSurvivor();
				if (Selected != null)
				{
					Live.Start(Selected);
				}
				this.Changed?.Invoke();
			}
		}

		private void EndRun(Run run)
		{
			runStarted = false;
			runBodyBound = false;
			Live.ClearReservations();
			overlay?.Close();
			this.Changed?.Invoke();
		}

		private void StageStarted(Stage stage)
		{
			Live.ClearReservations();
			this.Changed?.Invoke();
		}

		internal void Edit(string tier)
		{
			if (Selected != null)
			{
				if (Object.op_Implicit((Object)(object)Run.instance))
				{
					Live.Reconcile(Selected, tier);
				}
				Store.Dirty();
				this.Changed?.Invoke();
			}
		}

		internal void PickedUp(string item)
		{
			if (item != null && Live.Collect(item))
			{
				this.Changed?.Invoke();
			}
		}

		internal void Refresh()
		{
			this.Changed?.Invoke();
		}

		internal void Add(ItemDef item, int amount)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (Selected != null && Object.op_Implicit((Object)(object)item))
			{
				string tier = ((object)item.tier/*cast due to .constrained prefix*/).ToString();
				PlanEntry planEntry = Selected.entries.LastOrDefault((PlanEntry e) => e.tier == tier);
				if (planEntry != null && planEntry.item == ((Object)item).name)
				{
					planEntry.quantity = Math.Min(999, planEntry.quantity + amount);
				}
				else
				{
					Selected.entries.Add(new PlanEntry
					{
						item = ((Object)item).name,
						tier = tier,
						quantity = Math.Min(999, amount)
					});
				}
				Edit(tier);
			}
		}

		private void OnDisable()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			if (enabledHooks)
			{
				enabledHooks = false;
				Run.onRunStartGlobal -= StartRun;
				Run.onRunDestroyGlobal -= EndRun;
				Stage.onStageStartGlobal -= StageStarted;
				object obj = <>O.<0>__Display;
				if (obj == null)
				{
					hook_OnDisplayBegin val = CommandChoice.Display;
					<>O.<0>__Display = val;
					obj = (object)val;
				}
				PickupPickerController.OnDisplayBegin -= (hook_OnDisplayBegin)obj;
				object obj2 = <>O.<1>__Collected;
				if (obj2 == null)
				{
					hook_HandlePickupMessage val2 = CommandChoice.Collected;
					<>O.<1>__Collected = val2;
					obj2 = (object)val2;
				}
				GenericPickupController.HandlePickupMessage -= (hook_HandlePickupMessage)obj2;
				ItemInventoryDisplay.OnInventoryChanged -= new hook_OnInventoryChanged(SafeInventoryChanged);
				CommandChoice.Clear();
				Store?.Flush();
				overlay?.Close();
			}
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)overlay))
			{
				Object.Destroy((Object)(object)overlay);
			}
			ItemArtwork.Release();
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}
	}
	internal sealed class BuildEditor : MonoBehaviour
	{
		private sealed class QueueTile
		{
			internal PlanEntry Entry;

			internal RectTransform Slot;

			internal RectTransform Visual;

			internal PlanDrag Drag;

			internal CanvasGroup Opacity;
		}

		private BetterQueuePlugin plugin;

		private TextMeshProUGUI summary;

		private TextMeshProUGUI saveStatus;

		private TextMeshProUGUI queueHeading;

		private TextMeshProUGUI libraryHeading;

		private RectTransform planList;

		private RectTransform itemList;

		private RectTransform categoryList;

		private RectTransform planView;

		private RectTransform itemView;

		private RectTransform categoryView;

		private RectTransform searchView;

		private RectTransform helpView;

		private Button repeat;

		private LoopGlyph repeatIcon;

		private ColorBlock repeatColors;

		private ColorBlock categoryColors;

		private TMP_InputField search;

		private QueueOverlay scoreboardOwner;

		private readonly Dictionary<string, Button> categoryButtons = new Dictionary<string, Button>();

		private string[] displayedTiers = Array.Empty<string>();

		private string tier = "Tier1";

		private string query = "";

		private bool redraw = true;

		private float drawnWidth;

		private float drawnHeight;

		private readonly List<QueueTile> queueTiles = new List<QueueTile>();

		private readonly List<TooltipProvider> dragTooltips = new List<TooltipProvider>();

		private QueueTile dragged;

		private SurvivorPlan dragPlan;

		private PlanEntry[] dragEntries;

		private RectTransform dragLayer;

		private RectTransform dragGhost;

		private CanvasGroup ghostOpacity;

		private TextMeshProUGUI ghostOrder;

		private ScrollRect dragScroll;

		private bool scrollWasEnabled;

		private bool dragEnding;

		private bool dragCommit;

		private int dragSource;

		private int dragDestination;

		private int dragPointerId;

		private Vector2 dragPointer;

		private Vector2 grabOffset;

		private Vector2 settleFrom;

		private Camera dragCamera;

		private Camera ghostCamera;

		private float settleAt;

		private bool DragBusy => dragged != null;

		internal void Initialize(QueueOverlay owner = null)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0064: 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_00c0: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: 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_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			plugin = BetterQueuePlugin.Instance;
			plugin.Changed += Invalidate;
			scoreboardOwner = owner;
			RectTransform val = (RectTransform)((Component)this).transform;
			Widgets.PrepareNativeStyle();
			summary = Widgets.Text((Transform)(object)val, "Queue", 24, null, (TextAlignmentOptions)4097);
			saveStatus = Widgets.Text((Transform)(object)val, "Autosave", 16, Widgets.Muted, (TextAlignmentOptions)4100);
			categoryList = Widgets.Scroll((Transform)(object)val, "Categories", out categoryView, transparent: true);
			VerticalLayoutGroup obj = ((Component)categoryList).gameObject.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj).spacing = 4f;
			((LayoutGroup)obj).padding = new RectOffset(0, 10, 2, 2);
			bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true);
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = childControlWidth;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			((Component)categoryList).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			Widgets.Scrollbar(categoryView);
			repeat = Widgets.Button((Transform)(object)val, "", new UnityAction(ToggleRepeat));
			repeatColors = ((Selectable)repeat).colors;
			RectTransform val2 = Widgets.Rect(((Component)repeat).transform, "Loop icon");
			Widgets.Place(val2, 0.12f, 0.12f, 0.88f, 0.88f);
			repeatIcon = ((Component)val2).gameObject.AddComponent<LoopGlyph>();
			((Graphic)repeatIcon).raycastTarget = false;
			Widgets.Tip(((Component)repeat).gameObject, "Loop category", "Repeat this category's item order. Green means enabled.", Color.white);
			planList = Widgets.Scroll((Transform)(object)val, "Ordered build", out planView, transparent: true);
			AddGrid(planList);
			queueHeading = Widgets.Text((Transform)(object)val, "Add items below", 16, Widgets.Muted, (TextAlignmentOptions)4097);
			libraryHeading = Widgets.Text((Transform)(object)val, "Items", 16, Widgets.Muted, (TextAlignmentOptions)4097);
			itemList = Widgets.Scroll((Transform)(object)val, "Item library", out itemView, transparent: true);
			AddGrid(itemList);
			if (!Object.op_Implicit((Object)(object)scoreboardOwner))
			{
				CreateSearch(val);
			}
			TextMeshProUGUI val3 = Widgets.Text((Transform)(object)val, "Click: add / remove   |   Drag: reorder   |   Ctrl: 10", 14, Widgets.Muted, (TextAlignmentOptions)514);
			((TMP_Text)val3).enableAutoSizing = true;
			((TMP_Text)val3).fontSizeMin = 11f;
			((TMP_Text)val3).fontSizeMax = 14f;
			helpView = ((TMP_Text)val3).rectTransform;
		}

		private static void AddGrid(RectTransform list)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			GridLayoutGroup obj = ((Component)list).gameObject.AddComponent<GridLayoutGroup>();
			obj.constraint = (Constraint)1;
			obj.spacing = new Vector2(6f, 6f);
			((LayoutGroup)obj).padding = new RectOffset(4, 4, 4, 4);
			((Component)list).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
		}

		private void CreateSearch(RectTransform root)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			searchView = Widgets.Rect((Transform)(object)root, "Lobby item search");
			Image val = ((Component)searchView).gameObject.AddComponent<Image>();
			((Graphic)val).color = new Color(1f, 1f, 1f, 0.12f);
			search = ((Component)searchView).gameObject.AddComponent<TMP_InputField>();
			((Selectable)search).targetGraphic = (Graphic)(object)val;
			search.lineType = (LineType)0;
			search.characterLimit = 64;
			RectTransform val2 = Widgets.Rect((Transform)(object)searchView, "Text area");
			Widgets.Place(val2, 0.025f, 0.08f, 0.98f, 0.92f);
			((Component)val2).gameObject.AddComponent<RectMask2D>();
			TextMeshProUGUI val3 = Widgets.Text((Transform)(object)val2, "", 18, null, (TextAlignmentOptions)4097);
			Widgets.Place(((TMP_Text)val3).rectTransform, 0f, 0f, 1f, 1f);
			TextMeshProUGUI val4 = Widgets.Text((Transform)(object)val2, "Search items...", 18, Widgets.Muted, (TextAlignmentOptions)4097);
			Widgets.Place(((TMP_Text)val4).rectTransform, 0f, 0f, 1f, 1f);
			search.textViewport = val2;
			search.textComponent = (TMP_Text)(object)val3;
			search.placeholder = (Graphic)(object)val4;
			((UnityEvent<string>)(object)search.onValueChanged).AddListener((UnityAction<string>)delegate(string value)
			{
				query = value;
				Invalidate();
			});
			((Component)libraryHeading).gameObject.SetActive(false);
		}

		private string[] Tiers()
		{
			return ItemBrowser.Items.Select((ItemDef i) => ((object)i.tier/*cast due to .constrained prefix*/).ToString()).Concat<string>(plugin.Selected?.entries.Select((PlanEntry e) => e.tier) ?? Enumerable.Empty<string>()).Distinct()
				.ToArray();
		}

		private static void Box(RectTransform rect, float x, float top, float width, float height)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			rect.anchorMax = val;
			rect.anchorMin = val;
			rect.pivot = new Vector2(0f, 1f);
			rect.anchoredPosition = new Vector2(x, 0f - top);
			rect.sizeDelta = new Vector2(width, height);
		}

		private void Layout(QueueEditorLayout ui)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			Box(((TMP_Text)summary).rectTransform, 8f, 0f, ui.Width * 0.55f, 32f);
			Box(((TMP_Text)saveStatus).rectTransform, ui.Width * 0.63f, 0f, ui.Width * 0.37f - 8f, 32f);
			Box(categoryView, 8f, 38f, ui.SidebarWidth, ui.Height - 62f);
			Box(((TMP_Text)queueHeading).rectTransform, ui.ContentLeft, 38f, ui.ContentWidth, 20f);
			Box(planView, ui.ContentLeft, ui.PlanTop, ui.PlanWidth, ui.PlanHeight);
			Box((RectTransform)((Component)repeat).transform, ui.LoopLeft, ui.LoopTop, ui.Cell, ui.Cell);
			Box(((TMP_Text)libraryHeading).rectTransform, ui.ContentLeft, ui.LibraryHeadingTop, ui.ContentWidth, 20f);
			if (Object.op_Implicit((Object)(object)searchView))
			{
				Box(searchView, ui.ContentLeft, ui.LibraryHeadingTop, ui.ContentWidth, 30f);
			}
			Box(itemView, ui.ContentLeft, ui.LibraryTop, ui.ContentWidth, ui.LibraryHeight);
			Box(helpView, 8f, ui.Height - 22f, ui.Width - 16f, 20f);
			GridLayoutGroup component = ((Component)itemList).GetComponent<GridLayoutGroup>();
			component.constraintCount = ui.Columns;
			component.cellSize = new Vector2(ui.Cell, ui.Cell);
			GridLayoutGroup component2 = ((Component)planList).GetComponent<GridLayoutGroup>();
			component2.constraintCount = ui.PlanColumns;
			component2.cellSize = component.cellSize;
		}

		private void RenderCategories()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: 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_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			string[] array = Tiers();
			if (!displayedTiers.SequenceEqual(array))
			{
				displayedTiers = array;
				Widgets.Clear((Transform)(object)categoryList);
				categoryButtons.Clear();
				string[] array2 = array;
				foreach (string text in array2)
				{
					string selectedTier = text;
					Button val = Widgets.Button((Transform)(object)categoryList, ItemBrowser.TierName(text), (UnityAction)delegate
					{
						tier = selectedTier;
						((Component)planView).GetComponent<ScrollRect>().verticalNormalizedPosition = 1f;
						((Component)itemView).GetComponent<ScrollRect>().verticalNormalizedPosition = 1f;
						Invalidate();
					});
					categoryColors = ((Selectable)val).colors;
					LayoutElement obj = ((Component)val).gameObject.AddComponent<LayoutElement>();
					float minHeight = (obj.preferredHeight = 34f);
					obj.minHeight = minHeight;
					RectTransform obj2 = Widgets.Rect(((Component)val).transform, "Tier color");
					Widgets.Place(obj2, 0.025f, 0.16f, 0.06f, 0.84f);
					Image obj3 = ((Component)obj2).gameObject.AddComponent<Image>();
					((Graphic)obj3).color = ItemBrowser.Tint(text);
					((Graphic)obj3).raycastTarget = false;
					TextMeshProUGUI componentInChildren = ((Component)val).GetComponentInChildren<TextMeshProUGUI>();
					Widgets.Place(((TMP_Text)componentInChildren).rectTransform, 0.09f, 0.04f, 0.96f, 0.96f);
					((TMP_Text)componentInChildren).fontSizeMin = 11f;
					((TMP_Text)componentInChildren).fontSizeMax = 18f;
					Widgets.Tip(((Component)val).gameObject, ItemBrowser.TierName(text), "Edit this category's independent queue.", ItemBrowser.Tint(text));
					categoryButtons[text] = val;
				}
			}
			foreach (KeyValuePair<string, Button> categoryButton in categoryButtons)
			{
				ColorBlock colors = categoryColors;
				if (categoryButton.Key == tier)
				{
					((ColorBlock)(ref colors)).normalColor = new Color(0.68f, 0.61f, 0.3f);
				}
				((Selectable)categoryButton.Value).colors = colors;
			}
		}

		private void ToggleRepeat()
		{
			if (plugin.Selected != null)
			{
				if (!plugin.Selected.repeat.Remove(tier))
				{
					plugin.Selected.repeat.Add(tier);
				}
				plugin.Edit(tier);
			}
		}

		private void Invalidate()
		{
			redraw = true;
		}

		private void Update()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)plugin == (Object)null) && ItemBrowser.Ready)
			{
				Rect rect = ((RectTransform)((Component)this).transform).rect;
				if (Math.Abs(((Rect)(ref rect)).width - drawnWidth) > 2f || Math.Abs(((Rect)(ref rect)).height - drawnHeight) > 2f)
				{
					CancelQueueDrag();
					drawnWidth = ((Rect)(ref rect)).width;
					drawnHeight = ((Rect)(ref rect)).height;
					Layout(new QueueEditorLayout(drawnWidth, drawnHeight, (Object)(object)search != (Object)null));
					redraw = true;
				}
				if (DragBusy && !DragPlanValid())
				{
					CancelQueueDrag();
				}
				if (redraw && !DragBusy)
				{
					redraw = false;
					Render();
				}
				((TMP_Text)saveStatus).text = ((plugin.Store == null) ? "Loading profile..." : ((plugin.Store.Error != null) ? "Save error" : (plugin.Store.IsDirty ? "Saving..." : "Autosaved")));
			}
		}

		private void Render()
		{
			//IL_00e8: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Expected O, but got Unknown
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			if (plugin.Selected == null)
			{
				((TMP_Text)summary).text = "Select a survivor to start a build";
				return;
			}
			PlanEntry[] array = plugin.Selected.entries.Where((PlanEntry e) => e.tier == tier).ToArray();
			int num = array.Sum((PlanEntry e) => e.quantity);
			((TMP_Text)summary).text = "Queue";
			((TMP_Text)queueHeading).text = ItemBrowser.TierName(tier) + " - " + num + " picks";
			RenderCategories();
			bool flag = plugin.Selected.repeat.Contains(tier);
			((Graphic)repeatIcon).color = (Color)(flag ? new Color(0.4f, 1f, 0.5f) : Color.white);
			ColorBlock colors = repeatColors;
			if (flag)
			{
				((ColorBlock)(ref colors)).normalColor = new Color(0.2f, 0.55f, 0.27f);
				Color val = default(Color);
				((Color)(ref val))..ctor(0.4f, 0.9f, 0.48f);
				((ColorBlock)(ref colors)).selectedColor = val;
				((ColorBlock)(ref colors)).highlightedColor = val;
				((ColorBlock)(ref colors)).pressedColor = new Color(0.15f, 0.4f, 0.2f);
			}
			((Selectable)repeat).colors = colors;
			queueTiles.Clear();
			Widgets.Clear((Transform)(object)planList);
			for (int num2 = 0; num2 < array.Length; num2++)
			{
				BuildRow(array[num2], num2 + 1);
			}
			Widgets.Clear((Transform)(object)itemList);
			foreach (ItemDef item in ItemBrowser.Items.Where((ItemDef i) => ((object)i.tier/*cast due to .constrained prefix*/).ToString() == tier && (string.IsNullOrEmpty(query) || ItemBrowser.Name(i).IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)i).name.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0)))
			{
				ItemDef selected = item;
				Button val2 = Widgets.ItemButton((Transform)(object)itemList, (UnityAction)delegate
				{
					plugin.Add(selected, Amount());
				});
				Widgets.Icon(((Component)val2).transform, item, 0.09f, 0.14f, 0.91f, 0.93f);
				RectTransform obj = Widgets.Rect(((Component)val2).transform, "Tier stripe");
				Widgets.Place(obj, 0.1f, 0.02f, 0.9f, 0.065f);
				((Graphic)((Component)obj).gameObject.AddComponent<Image>()).color = ItemBrowser.Tint(tier);
				((Graphic)((Component)obj).GetComponent<Image>()).raycastTarget = false;
				ItemTooltip.Attach(((Component)val2).gameObject, item, "Click to add - Ctrl adds 10 - Right-click removes");
				((Component)val2).gameObject.AddComponent<LibraryClick>().Initialize(item);
				if (!ItemBrowser.Usable(((Object)item).name))
				{
					((Selectable)val2).interactable = false;
				}
			}
		}

		internal static int Amount()
		{
			if (!Input.GetKey((KeyCode)306) && !Input.GetKey((KeyCode)305))
			{
				return 1;
			}
			return 10;
		}

		private void BuildRow(PlanEntry entry, int order)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = Widgets.Rect((Transform)(object)planList, "Queue slot " + order);
			RectTransform val2 = (RectTransform)((Component)Widgets.ItemButton((Transform)(object)val, (UnityAction)delegate
			{
				Resize(entry, -Amount());
			})).transform;
			Widgets.Place(val2, 0f, 0f, 1f, 1f);
			TextMeshProUGUI obj = Widgets.Text((Transform)(object)val2, order.ToString(), 13, Widgets.Muted, (TextAlignmentOptions)4097);
			Widgets.Place(((TMP_Text)obj).rectTransform, 0.05f, 0.69f, 0.3f, 1f);
			ItemDef item = ItemBrowser.Find(entry.item);
			Widgets.Icon((Transform)(object)val2, item, 0.1f, 0.15f, 0.9f, 0.93f);
			((TMP_Text)obj).transform.SetAsLastSibling();
			TextMeshProUGUI obj2 = Widgets.Text((Transform)(object)val2, "×" + entry.quantity, 15, Color.white, (TextAlignmentOptions)4100);
			((TMP_Text)obj2).enableAutoSizing = true;
			((TMP_Text)obj2).fontSizeMin = 10f;
			((TMP_Text)obj2).fontSizeMax = 15f;
			Widgets.Place(((TMP_Text)obj2).rectTransform, 0.22f, 0.01f, 0.94f, 0.29f);
			ItemTooltip.Attach(((Component)val2).gameObject, item, "Click -1 - Right-click +1 - Ctrl changes 10\nDrag to reorder" + (Object.op_Implicit((Object)(object)Run.instance) ? ("\n" + plugin.Live.Remaining(entry.id) + " picks left in this run") : ""));
			PlanDrag planDrag = ((Component)val2).gameObject.AddComponent<PlanDrag>();
			planDrag.Initialize(this);
			CanvasGroup opacity = ((Component)val2).gameObject.AddComponent<CanvasGroup>();
			queueTiles.Add(new QueueTile
			{
				Entry = entry,
				Slot = val,
				Visual = val2,
				Drag = planDrag,
				Opacity = opacity
			});
			((Component)val2).gameObject.AddComponent<QueueClick>().Initialize(this, entry);
		}

		internal void Resize(PlanEntry entry, int delta)
		{
			if (plugin.Selected != null && plugin.Selected.entries.Contains(entry))
			{
				entry.quantity = Math.Min(999, entry.quantity + delta);
				if (entry.quantity <= 0)
				{
					plugin.Selected.entries.Remove(entry);
				}
				plugin.Edit(entry.tier);
			}
		}

		private void OnDisable()
		{
			FinishReleasedDrag();
		}

		private void OnDestroy()
		{
			CancelQueueDrag();
			if (Object.op_Implicit((Object)(object)plugin))
			{
				plugin.Changed -= Invalidate;
			}
		}

		private bool DragPlanValid()
		{
			if (!Object.op_Implicit((Object)(object)plugin) || plugin.Selected != dragPlan || dragged == null || tier != dragged.Entry.tier)
			{
				return false;
			}
			int num = 0;
			foreach (PlanEntry entry in dragPlan.entries)
			{
				if (entry.tier == tier && (num >= dragEntries.Length || entry != dragEntries[num++]))
				{
					return false;
				}
			}
			return num == dragEntries.Length;
		}

		internal void BeginQueueDrag(PlanDrag source, PointerEventData data)
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_044b: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_0458: Unknown result type (might be due to invalid IL or missing references)
			//IL_0463: Unknown result type (might be due to invalid IL or missing references)
			if (DragBusy || !Object.op_Implicit((Object)(object)plugin) || plugin.Selected == null)
			{
				return;
			}
			QueueTile queueTile = queueTiles.FirstOrDefault((QueueTile t) => (Object)(object)t.Drag == (Object)(object)source);
			Canvas componentInParent = ((Component)source).GetComponentInParent<Canvas>();
			if (queueTile == null || !Object.op_Implicit((Object)(object)componentInParent))
			{
				return;
			}
			try
			{
				Canvas.ForceUpdateCanvases();
				LayoutRebuilder.ForceRebuildLayoutImmediate(planList);
				dragged = queueTile;
				dragPlan = plugin.Selected;
				dragEntries = queueTiles.Select((QueueTile t) => t.Entry).ToArray();
				dragSource = (dragDestination = queueTiles.IndexOf(queueTile));
				dragPointerId = data.pointerId;
				dragPointer = data.position;
				dragCamera = data.pressEventCamera;
				Canvas rootCanvas = componentInParent.rootCanvas;
				ghostCamera = (((int)rootCanvas.renderMode == 0) ? null : (Object.op_Implicit((Object)(object)rootCanvas.worldCamera) ? rootCanvas.worldCamera : dragCamera));
				dragLayer = Widgets.Rect(((Component)this).transform, "BetterQueue drag preview");
				Widgets.Place(dragLayer, 0f, 0f, 1f, 1f);
				((Graphic)((Component)dragLayer).gameObject.AddComponent<Image>()).color = Color.clear;
				((Transform)dragLayer).SetAsLastSibling();
				dragGhost = Widgets.Rect((Transform)(object)dragLayer, "Dragged item");
				RectTransform obj = dragGhost;
				Vector2 anchorMin = (dragGhost.anchorMax = new Vector2(0.5f, 0.5f));
				obj.anchorMin = anchorMin;
				Vector3 lossyScale = ((Transform)queueTile.Visual).lossyScale;
				Vector3 lossyScale2 = ((Transform)dragLayer).lossyScale;
				RectTransform obj2 = dragGhost;
				Rect rect = queueTile.Visual.rect;
				float num = ((Rect)(ref rect)).width * Mathf.Abs(lossyScale.x / lossyScale2.x);
				rect = queueTile.Visual.rect;
				obj2.sizeDelta = new Vector2(num, ((Rect)(ref rect)).height * Mathf.Abs(lossyScale.y / lossyScale2.y));
				Image component = ((Component)queueTile.Visual).GetComponent<Image>();
				Image obj3 = ((Component)dragGhost).gameObject.AddComponent<Image>();
				obj3.sprite = component.sprite;
				((Graphic)obj3).material = ((Graphic)component).material;
				obj3.type = component.type;
				obj3.pixelsPerUnitMultiplier = component.pixelsPerUnitMultiplier;
				((Graphic)obj3).color = ((Graphic)component).color;
				((Graphic)obj3).raycastTarget = false;
				Outline obj4 = ((Component)dragGhost).gameObject.AddComponent<Outline>();
				((Shadow)obj4).effectColor = new Color(1f, 0.84f, 0.36f, 0.85f);
				((Shadow)obj4).effectDistance = new Vector2(1f, -1f);
				Widgets.Icon((Transform)(object)dragGhost, ItemBrowser.Find(queueTile.Entry.item), 0.1f, 0.15f, 0.9f, 0.93f);
				ghostOrder = Widgets.Text((Transform)(object)dragGhost, (dragDestination + 1).ToString(), 13, Widgets.Muted, (TextAlignmentOptions)4097);
				Widgets.Place(((TMP_Text)ghostOrder).rectTransform, 0.05f, 0.69f, 0.3f, 1f);
				TextMeshProUGUI obj5 = Widgets.Text((Transform)(object)dragGhost, "×" + queueTile.Entry.quantity, 15, Color.white, (TextAlignmentOptions)4100);
				((TMP_Text)obj5).enableAutoSizing = true;
				((TMP_Text)obj5).fontSizeMin = 10f;
				((TMP_Text)obj5).fontSizeMax = 15f;
				Widgets.Place(((TMP_Text)obj5).rectTransform, 0.22f, 0.01f, 0.94f, 0.29f);
				ghostOpacity = ((Component)dragGhost).gameObject.AddComponent<CanvasGroup>();
				ghostOpacity.blocksRaycasts = false;
				ghostOpacity.interactable = false;
				RectTransform obj6 = dragLayer;
				RectTransform visual = queueTile.Visual;
				rect = queueTile.Visual.rect;
				Vector2 val2 = Vector2.op_Implicit(((Transform)obj6).InverseTransformPoint(((Transform)visual).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center))));
				grabOffset = val2 - PointerInOverlay();
				dragGhost.anchoredPosition = val2;
				dragged.Opacity.alpha = 0.2f;
				dragScroll = ((Component)planView).GetComponent<ScrollRect>();
				scrollWasEnabled = ((Behaviour)dragScroll).enabled;
				dragScroll.StopMovement();
				((Behaviour)dragScroll).enabled = false;
				TooltipProvider[] componentsInChildren = ((Component)this).GetComponentsInChildren<TooltipProvider>();
				foreach (TooltipProvider val3 in componentsInChildren)
				{
					if (((Behaviour)val3).enabled)
					{
						TooltipController.RemoveTooltip(val3);
						((Behaviour)val3).enabled = false;
						dragTooltips.Add(val3);
					}
				}
				data.eligibleForClick = false;
			}
			catch (Exception ex)
			{
				data.eligibleForClick = false;
				CancelQueueDrag();
				Debug.LogWarning((object)("[BetterQueue] Drag preview cancelled: " + ex.Message));
			}
		}

		internal void MoveQueueDrag(PlanDrag source, PointerEventData data)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (DragBusy && !dragEnding && !((Object)(object)dragged.Drag != (Object)(object)source) && data.pointerId == dragPointerId)
			{
				dragPointer = data.position;
				data.eligibleForClick = false;
			}
		}

		internal void EndQueueDrag(PlanDrag source, PointerEventData data)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			if (DragBusy && !dragEnding && !((Object)(object)dragged.Drag != (Object)(object)source) && data.pointerId == dragPointerId)
			{
				dragPointer = data.position;
				data.eligibleForClick = false;
				dragCommit = DragPlanValid() && PointerInsideQueue();
				dragDestination = (dragCommit ? PointerSlot() : dragSource);
				if (dragDestination < 0)
				{
					dragDestination = dragSource;
					dragCommit = false;
				}
				((TMP_Text)ghostOrder).text = (dragDestination + 1).ToString();
				dragEnding = true;
				settleAt = Time.unscaledTime;
				settleFrom = dragGhost.anchoredPosition;
			}
		}

		private bool PointerInsideQueue()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return RectTransformUtility.RectangleContainsScreenPoint(planView, dragPointer, dragCamera);
		}

		private Vector2 PointerInOverlay()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Vector2 result = default(Vector2);
			RectTransformUtility.ScreenPointToLocalPointInRectangle(dragLayer, dragPointer, ghostCamera, ref result);
			return result;
		}

		private int PointerSlot()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(planList, dragPointer, dragCamera, ref val))
			{
				return dragSource;
			}
			GridLayoutGroup component = ((Component)planList).GetComponent<GridLayoutGroup>();
			float x = val.x;
			Rect rect = planList.rect;
			double x2 = x - ((Rect)(ref rect)).xMin;
			rect = planList.rect;
			return QueueDragRules.NearestSlot(x2, ((Rect)(ref rect)).yMax - val.y, component.constraintCount, queueTiles.Count, component.cellSize.x, component.spacing.x, ((LayoutGroup)component).padding.left, ((LayoutGroup)component).padding.top);
		}

		private void ScrollQueueDuringDrag(float delta)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = planList.rect;
			float height = ((Rect)(ref rect)).height;
			rect = planView.rect;
			float num = height - ((Rect)(ref rect)).height;
			Vector2 val = default(Vector2);
			if (!(num < 1f) && RectTransformUtility.ScreenPointToLocalPointInRectangle(planView, dragPointer, dragCamera, ref val))
			{
				rect = planView.rect;
				float num2 = Mathf.Min(20f, ((Rect)(ref rect)).height * 0.25f);
				float num3 = 0f;
				rect = planView.rect;
				float num4 = ((Rect)(ref rect)).yMax - val.y;
				float y = val.y;
				rect = planView.rect;
				float num5 = y - ((Rect)(ref rect)).yMin;
				if (num4 < num2)
				{
					num3 = 1f - Mathf.Clamp01(num4 / num2);
				}
				else if (num5 < num2)
				{
					num3 = 0f - (1f - Mathf.Clamp01(num5 / num2));
				}
				dragScroll.verticalNormalizedPosition = Mathf.Clamp01(dragScroll.verticalNormalizedPosition + num3 * 300f * delta / num);
			}
		}

		private void SlideQueueTiles(float blend)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < queueTiles.Count; i++)
			{
				int index = QueueDragRules.PreviewSlot(i, dragSource, dragDestination);
				QueueTile queueTile = queueTiles[i];
				Vector2 val = Vector2.op_Implicit(((Transform)queueTiles[index].Slot).localPosition - ((Transform)queueTile.Slot).localPosition);
				queueTile.Visual.anchoredPosition = Vector2.Lerp(queueTile.Visual.anchoredPosition, val, blend);
			}
		}

		private void LateUpdate()
		{
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: 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)
			if (!DragBusy)
			{
				return;
			}
			if (Input.GetKeyDown((KeyCode)27))
			{
				CancelQueueDrag();
				return;
			}
			if (!DragPlanValid() || !Object.op_Implicit((Object)(object)dragGhost))
			{
				CancelQueueDrag();
				return;
			}
			float num = Mathf.Min(Time.unscaledDeltaTime, 0.05f);
			float num2 = 1f - Mathf.Exp(-26f * num);
			if (!dragEnding)
			{
				bool flag = PointerInsideQueue();
				if (flag)
				{
					ScrollQueueDuringDrag(num);
				}
				int num3 = (flag ? PointerSlot() : dragSource);
				if (num3 < 0)
				{
					num3 = dragSource;
				}
				if (num3 != dragDestination)
				{
					dragDestination = num3;
					((TMP_Text)ghostOrder).text = (num3 + 1).ToString();
				}
				ghostOpacity.alpha = (flag ? 0.97f : 0.6f);
				dragGhost.anchoredPosition = Vector2.Lerp(dragGhost.anchoredPosition, PointerInOverlay() + grabOffset, 1f - Mathf.Exp(-45f * num));
				((Transform)dragGhost).localScale = Vector3.Lerp(((Transform)dragGhost).localScale, Vector3.one * 1.06f, num2);
				SlideQueueTiles(num2);
			}
			else
			{
				float num4 = Mathf.Clamp01((Time.unscaledTime - settleAt) / 0.14f);
				float num5 = num4 * num4 * (3f - 2f * num4);
				RectTransform slot = queueTiles[dragDestination].Slot;
				RectTransform obj = dragLayer;
				Rect rect = slot.rect;
				Vector2 val = Vector2.op_Implicit(((Transform)obj).InverseTransformPoint(((Transform)slot).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center))));
				dragGhost.anchoredPosition = Vector2.Lerp(settleFrom, val, num5);
				((Transform)dragGhost).localScale = Vector3.one * Mathf.Lerp(1.06f, 1f, num5);
				ghostOpacity.alpha = 1f - num5;
				dragged.Opacity.alpha = Mathf.Lerp(0.2f, 1f, num5);
				SlideQueueTiles(num2);
				if (num4 >= 1f)
				{
					FinishQueueDrag(dragCommit, renderNow: true);
				}
			}
		}

		private void FinishQueueDrag(bool commit, bool renderNow)
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			if (!DragBusy)
			{
				return;
			}
			string text = dragged.Entry.tier;
			bool flag = commit && DragPlanValid() && QueueDragRules.Commit(dragPlan, dragged.Entry, dragDestination);
			dragged = null;
			dragPlan = null;
			dragEntries = null;
			dragEnding = (dragCommit = false);
			if (Object.op_Implicit((Object)(object)dragLayer))
			{
				((Component)dragLayer).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)dragLayer).gameObject);
			}
			dragLayer = (dragGhost = null);
			ghostOpacity = null;
			ghostOrder = null;
			foreach (QueueTile queueTile in queueTiles)
			{
				if (Object.op_Implicit((Object)(object)queueTile.Visual))
				{
					queueTile.Visual.anchoredPosition = Vector2.zero;
				}
				if (Object.op_Implicit((Object)(object)queueTile.Opacity))
				{
					queueTile.Opacity.alpha = 1f;
				}
			}
			foreach (TooltipProvider dragTooltip in dragTooltips)
			{
				if (Object.op_Implicit((Object)(object)dragTooltip))
				{
					((Behaviour)dragTooltip).enabled = true;
				}
			}
			dragTooltips.Clear();
			if (Object.op_Implicit((Object)(object)dragScroll))
			{
				((Behaviour)dragScroll).enabled = scrollWasEnabled;
				dragScroll.StopMovement();
			}
			dragScroll = null;
			if (flag)
			{
				plugin.Edit(text);
			}
			if (flag && renderNow && ((Behaviour)this).isActiveAndEnabled)
			{
				redraw = false;
				Render();
				LayoutRebuilder.ForceRebuildLayoutImmediate(planList);
			}
		}

		private void CancelQueueDrag()
		{
			FinishQueueDrag(commit: false, renderNow: false);
		}

		private void OnApplicationFocus(bool focused)
		{
			if (!focused)
			{
				CancelQueueDrag();
			}
		}

		private void FinishReleasedDrag()
		{
			FinishQueueDrag(dragEnding && dragCommit, renderNow: false);
		}

		internal void DragTileDisabled(PlanDrag tile)
		{
			if (DragBusy && (Object)(object)dragged.Drag == (Object)(object)tile)
			{
				FinishReleasedDrag();
			}
		}
	}
	internal sealed class QueueClick : MonoBehaviour, IPointerClickHandler, IEventSystemHandler
	{
		private BuildEditor editor;

		private PlanEntry entry;

		internal void Initialize(BuildEditor owner, PlanEntry step)
		{
			editor = owner;
			entry = step;
		}

		public void OnPointerClick(PointerEventData data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)data.button == 1)
			{
				editor.Resize(entry, (!Input.GetKey((KeyCode)306) && !Input.GetKey((KeyCode)305)) ? 1 : 10);
			}
		}
	}
	internal sealed class LibraryClick : MonoBehaviour, IPointerClickHandler, IEventSystemHandler
	{
		private ItemDef item;

		internal void Initialize(ItemDef target)
		{
			item = target;
		}

		public void OnPointerClick(PointerEventData data)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			BetterQueuePlugin instance = BetterQueuePlugin.Instance;
			if ((int)data.button != 1 || instance?.Selected == null)
			{
				return;
			}
			PlanEntry planEntry = instance.Selected.entries.LastOrDefault((PlanEntry e) => e.item == ((Object)item).name);
			if (planEntry != null)
			{
				planEntry.quantity -= BuildEditor.Amount();
				if (planEntry.quantity <= 0)
				{
					instance.Selected.entries.Remove(planEntry);
				}
				instance.Edit(planEntry.tier);
			}
		}
	}
	internal sealed class PlanDrag : MonoBehaviour, IInitializePotentialDragHandler, IEventSystemHandler, IBeginDragHandler, IDragHandler, IEndDragHandler
	{
		private BuildEditor editor;

		internal void Initialize(BuildEditor owner)
		{
			editor = owner;
		}

		public void OnInitializePotentialDrag(PointerEventData data)
		{
			data.useDragThreshold = true;
		}

		public void OnBeginDrag(PointerEventData data)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if ((int)data.button == 0)
			{
				editor.BeginQueueDrag(this, data);
			}
		}

		public void OnDrag(PointerEventData data)
		{
			editor.MoveQueueDrag(this, data);
		}

		public void OnEndDrag(PointerEventData data)
		{
			editor.EndQueueDrag(this, data);
		}

		private void OnDisable()
		{
			if (Object.op_Implicit((Object)(object)editor))
			{
				editor.DragTileDisabled(this);
			}
		}
	}
	internal static class CommandChoice
	{
		private static readonly HashSet<PickupPickerController> submitting = new HashSet<PickupPickerController>();

		private static readonly MethodInfo hostChoice = typeof(PickupPickerController).GetMethod("HandlePickupSelected", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly Type pickupMessageType = typeof(GenericPickupController).GetNestedType("PickupMessage", BindingFlags.NonPublic);

		private static readonly FieldInfo pickupMaster = pickupMessageType?.GetField("masterGameObject");

		private static readonly FieldInfo pickupState = pickupMessageType?.GetField("pickupState");

		private static readonly FieldInfo pickupAdded = pickupMessageType?.GetField("addedQuantity");

		private static bool pickupWarning;

		internal static void Clear()
		{
			submitting.Clear();
		}

		internal static void Display(orig_OnDisplayBegin original, PickupPickerController picker, NetworkUIPromptController prompt, LocalUser user, CameraRigController camera)
		{
			BetterQueuePlugin instance = BetterQueuePlugin.Instance;
			GameObject commandCubePrefab = CommandArtifactManager.commandCubePrefab;
			GameObject val = ((!Object.op_Implicit((Object)(object)commandCubePrefab)) ? null : commandCubePrefab.GetComponent<PickupPickerController>()?.panelPrefab);
			if (Object.op_Implicit((Object)(object)instance) && instance.AutoSelect.Value && Object.op_Implicit((Object)(object)Run.instance) && Object.op_Implicit((Object)(object)val) && (Object)(object)picker.panelPrefab == (Object)(object)val && user == LocalUserManager.GetFirstLocalUser())
			{
				PlanEntry planEntry = instance.Live.Next(ItemBrowser.Usable).FirstOrDefault((PlanEntry entry) => FindOption(picker, entry.item) >= 0);
				if (planEntry != null)
				{
					if (submitting.Add(picker))
					{
						((MonoBehaviour)instance).StartCoroutine(Submit(instance, picker, prompt, user, camera, original, planEntry));
					}
					return;
				}
			}
			original.Invoke(picker, prompt, user, camera);
		}

		private static int FindOption(PickupPickerController picker, string item)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)picker) || picker.options == null)
			{
				return -1;
			}
			for (int i = 0; i < picker.options.Length; i++)
			{
				Option val = picker.options[i];
				if (val.available && !((UniquePickup)(ref val.pickup)).isTempItem && !val.pickup.isRental && ItemBrowser.PickupName(val.pickup.pickupIndex) == item)
				{
					return i;
				}
			}
			return -1;
		}

		private static IEnumerator Submit(BetterQueuePlugin plugin, PickupPickerController picker, NetworkUIPromptController prompt, LocalUser user, CameraRigController camera, orig_OnDisplayBegin original, PlanEntry desired)
		{
			yield return null;
			try
			{
				if (!Object.op_Implicit((Object)(object)picker) || !Object.op_Implicit((Object)(object)plugin) || !((Behaviour)plugin).isActiveAndEnabled)
				{
					yield break;
				}
				PlanEntry planEntry = plugin.Live.Next(ItemBrowser.Usable).FirstOrDefault((PlanEntry e) => e.id == desired.id);
				int num = ((planEntry != null) ? FindOption(picker, planEntry.item) : (-1));
				if (num < 0)
				{
					original.Invoke(picker, prompt, user, camera);
					yield break;
				}
				RunPlan.Reservation reservation = plugin.Live.Reserve(planEntry.id);
				if (reservation == null)
				{
					original.Invoke(picker, prompt, user, camera);
					yield break;
				}
				try
				{
					if (NetworkServer.active)
					{
						if (hostChoice == null)
						{
							throw new MissingMethodException("RoR2 Command choice API changed.");
						}
						hostChoice.Invoke(picker, new object[1] { num });
					}
					else
					{
						if (!Object.op_Implicit((Object)(object)prompt))
						{
							throw new InvalidOperationException("Command cube has no network prompt.");
						}
						NetworkWriter val = prompt.BeginMessageToServer();
						val.Write((byte)0);
						val.Write(num);
						prompt.FinishMessageToServer(val);
					}
					plugin.Refresh();
				}
				catch (Exception ex)
				{
					plugin.Live.Cancel(reservation);
					Debug.LogWarning((object)("[BetterQueue] Selection failed; restoring manual picker: " + ex.Message));
					if (Object.op_Implicit((Object)(object)picker))
					{
						original.Invoke(picker, prompt, user, camera);
					}
				}
			}
			finally
			{
				submitting.Remove(picker);
			}
		}

		internal static void Collected(orig_HandlePickupMessage original, NetworkMessage netMsg)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = null;
			UniquePickup val2 = UniquePickup.none;
			uint num = 0u;
			NetworkReader reader = netMsg.reader;
			uint position = reader.Position;
			try
			{
				byte[] array;
				try
				{
					array = reader.ReadBytes(reader.Length - (int)position);
				}
				finally
				{
					reader.SeekZero();
					if (position != 0)
					{
						reader.ReadBytes((int)position);
					}
				}
				MessageBase val3 = (MessageBase)Activator.CreateInstance(pickupMessageType, nonPublic: true);
				val3.Deserialize(new NetworkReader(array));
				object? value = pickupMaster.GetValue(val3);
				val = (GameObject)((value is GameObject) ? value : null);
				val2 = (UniquePickup)pickupState.GetValue(val3);
				num = (uint)pickupAdded.GetValue(val3);
			}
			catch (Exception ex)
			{
				if (!pickupWarning)
				{
					pickupWarning = true;
					Debug.LogWarning((object)("[BetterQueue] Pickup receipt could not be decoded; native collection is unchanged: " + ex.Message));
				}
			}
			original.Invoke(netMsg);
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			CharacterMaster val4 = ((firstLocalUser != null) ? firstLocalUser.cachedMaster : null);
			if (!Object.op_Implicit((Object)(object)val4) || !((Object)(object)val == (Object)(object)((Component)val4).gameObject) || ((UniquePickup)(ref val2)).isTempItem || val2.isRental)
			{
				return;
			}
			string item = ItemBrowser.PickupName(val2.pickupIndex);
			for (uint num2 = 0u; num2 < num; num2++)
			{
				BetterQueuePlugin instance = BetterQueuePlugin.Instance;
				if (instance != null && instance.Live.Collect(item))
				{
					BetterQueuePlugin.Instance.Refresh();
					continue;
				}
				break;
			}
		}
	}
	internal static class ItemArtwork
	{
		private static readonly Dictionary<string, AsyncOperationHandle<Sprite>> images = new Dictionary<string, AsyncOperationHandle<Sprite>>();

		internal static void Assign(Image target, ItemDef item)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)item))
			{
				((Behaviour)target).enabled = false;
				return;
			}
			if (Object.op_Implicit((Object)(object)item.pickupIconSprite))
			{
				target.sprite = item.pickupIconSprite;
				return;
			}
			AssetReferenceT<Sprite> pickupIconSpriteReference = item.pickupIconSpriteReference;
			if (pickupIconSpriteReference == null || !((AssetReference)pickupIconSpriteReference).RuntimeKeyIsValid())
			{
				((Behaviour)target).enabled = false;
				return;
			}
			if (!images.TryGetValue(((Object)item).name, out var value))
			{
				value = Addressables.LoadAssetAsync<Sprite>(((AssetReference)pickupIconSpriteReference).RuntimeKey);
				images[((Object)item).name] = value;
			}
			if (value.IsDone)
			{
				target.sprite = value.Result;
				((Behaviour)target).enabled = Object.op_Implicit((Object)(object)target.sprite);
				return;
			}
			((Behaviour)target).enabled = false;
			value.Completed += delegate(AsyncOperationHandle<Sprite> loaded)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Invalid comparison between Unknown and I4
				if (Object.op_Implicit((Object)(object)target))
				{
					target.sprite = (((int)loaded.Status == 1) ? loaded.Result : null);
					((Behaviour)target).enabled = Object.op_Implicit((Object)(object)target.sprite);
				}
			};
		}

		internal static void Release()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			foreach (AsyncOperationHandle<Sprite> value in images.Values)
			{
				if (value.IsValid())
				{
					Addressables.Release<Sprite>(value);
				}
			}
			images.Clear();
		}
	}
	internal static class ItemBrowser
	{
		private static readonly Dictionary<string, ItemDef> byName = new Dictionary<string, ItemDef>();

		internal static List<ItemDef> Items { get; private set; } = new List<ItemDef>();

		internal static bool Ready => Items.Count > 0;

		internal static void Initialize()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Invalid comparison between Unknown and I4
			if (Ready || ItemCatalog.itemCount == 0)
			{
				return;
			}
			Enumerator<ItemDef> enumerator = ItemCatalog.allItemDefs.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					ItemDef current = enumerator.Current;
					if (Object.op_Implicit((Object)(object)current))
					{
						byName[((Object)current).name] = current;
						if (!current.hidden && (int)current.tier != 5 && current.canRemove)
						{
							Items.Add(current);
						}
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
			Items = Items.OrderBy((ItemDef i) => (int)i.tier).ThenBy(Name).ToList();
		}

		internal static ItemDef Find(string key)
		{
			if (key == null || !byName.TryGetValue(key, out var value))
			{
				return null;
			}
			return value;
		}

		internal static string Name(ItemDef item)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				return "Missing item";
			}
			return Language.GetString(item.nameToken);
		}

		internal static string TierOf(string key)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			ItemDef val = Find(key);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return "Missing";
			}
			return ((object)val.tier/*cast due to .constrained prefix*/).ToString();
		}

		internal unsafe static string LegacyTier(string key)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			foreach (ItemTier item in Items.Select((ItemDef i) => i.tier).Distinct())
			{
				ItemTierDef itemTierDef = ItemTierCatalog.GetItemTierDef(item);
				if (Object.op_Implicit((Object)(object)itemTierDef) && ((Object)itemTierDef).name == key)
				{
					return ((object)(*(ItemTier*)(&item))/*cast due to .constrained prefix*/).ToString();
				}
			}
			return key?.Replace("TierDef", "").Replace("Def", "") ?? "Missing";
		}

		internal static string TierName(string key)
		{
			return key switch
			{
				"Tier1" => "White", 
				"Tier2" => "Green", 
				"Tier3" => "Red", 
				"VoidTier1" => "Void common", 
				"VoidTier2" => "Void uncommon", 
				"VoidTier3" => "Void legendary", 
				"Cursed" => "Hallowed", 
				_ => key, 
			};
		}

		internal static Color Tint(string tier)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (Enum.TryParse<ItemTier>(tier, out ItemTier result))
			{
				ItemTierDef itemTierDef = ItemTierCatalog.GetItemTierDef(result);
				if (Object.op_Implicit((Object)(object)itemTierDef))
				{
					return Color32.op_Implicit(ColorCatalog.GetColor(itemTierDef.colorIndex));
				}
			}
			return new Color(0.6f, 0.65f, 0.7f);
		}

		internal static bool Usable(string key)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			ItemDef val = Find(key);
			if (Object.op_Implicit((Object)(object)val))
			{
				if (Object.op_Implicit((Object)(object)Run.instance))
				{
					return Run.instance.IsPickupAvailable(PickupCatalog.FindPickupIndex(val.itemIndex));
				}
				return true;
			}
			return false;
		}

		internal static string PickupName(PickupIndex index)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			PickupDef pickupDef = PickupCatalog.GetPickupDef(index);
			ItemDef val = ((pickupDef != null) ? ItemCatalog.GetItemDef(pickupDef.itemIndex) : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			return ((Object)val).name;
		}
	}
	internal static class ItemDescription
	{
		private static bool resolved;

		private static bool warned;

		private static Func<ItemDef, int, CharacterMaster, bool, bool, string> describe;

		internal static string For(ItemDef item)
		{
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)item))
			{
				return "This item is not currently installed.";
			}
			if (!resolved)
			{
				resolved = true;
				try
				{
					MethodInfo methodInfo = Type.GetType("LookingGlass.ItemStatsNameSpace.ItemStats, LookingGlass", throwOnError: false)?.GetMethod("GetItemDescription", BindingFlags.Static | BindingFlags.Public, null, new Type[5]
					{
						typeof(ItemDef),
						typeof(int),
						typeof(CharacterMaster),
						typeof(bool),
						typeof(bool)
					}, null);
					if (methodInfo != null && methodInfo.ReturnType == typeof(string))
					{
						describe = (Func<ItemDef, int, CharacterMaster, bool, bool, string>)Delegate.CreateDelegate(typeof(Func<ItemDef, int, CharacterMaster, bool, bool, string>), methodInfo);
					}
				}
				catch (Exception error)
				{
					Warn(error);
				}
			}
			if (describe != null)
			{
				try
				{
					LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
					CharacterMaster val = ((firstLocalUser != null) ? firstLocalUser.cachedMaster : null);
					int arg = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.inventory)) ? val.inventory.GetItemCountEffective(item.itemIndex) : 0);
					string text = describe(item, arg, val, arg4: true, arg5: false);
					if (!string.IsNullOrEmpty(text))
					{
						return text;
					}
				}
				catch (Exception error2)
				{
					Warn(error2);
				}
			}
			return Language.GetString(Language.IsTokenInvalid(item.descriptionToken) ? item.pickupToken : item.descriptionToken);
		}

		private static void Warn(Exception error)
		{
			if (!warned)
			{
				warned = true;
				Debug.LogWarning((object)("[BetterQueue] Optional LookingGlass tooltip unavailable; using the full item description. " + error.GetType().Name));
			}
		}
	}
	internal sealed class ItemTooltip : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler, ISelectHandler
	{
		private ItemDef item;

		private string instructions;

		private TooltipProvider tip;

		internal static void Attach(GameObject target, ItemDef item, string instructions)
		{
			ItemTooltip itemTooltip = target.AddComponent<ItemTooltip>();
			itemTooltip.item = item;
			itemTooltip.instructions = instructions;
			itemTooltip.tip = target.AddComponent<TooltipProvider>();
			itemTooltip.tip.AllowTooltipOnNavigationSelect = false;
			itemTooltip.Refresh();
		}

		private void Refresh()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			tip.titleToken = (Object.op_Implicit((Object)(object)item) ? item.nameToken : "");
			tip.overrideTitleText = (Object.op_Implicit((Object)(object)item) ? "" : "Missing item");
			ItemTierDef val = (Object.op_Implicit((Object)(object)item) ? ItemTierCatalog.GetItemTierDef(item.tier) : null);
			tip.titleColor = (Object.op_Implicit((Object)(object)val) ? Color32.op_Implicit(ColorCatalog.GetColor(val.darkColorIndex)) : Color.white);
			tip.bodyColor = Color.white;
			tip.overrideBodyText = ItemDescription.For(item) + "\n\n<size=85%><color=#BFC3CA>" + instructions + "</color></size>";
		}

		public void OnPointerEnter(PointerEventData data)
		{
			tip.AllowTooltipOnNavigationSelect = false;
			Refresh();
		}

		public void OnPointerExit(PointerEventData data)
		{
			tip.AllowTooltipOnNavigationSelect = false;
			TooltipController.RemoveTooltip(tip);
		}

		public void OnSelect(BaseEventData data)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			EventSystem current = EventSystem.current;
			MPEventSystem val = (MPEventSystem)(object)((current is MPEventSystem) ? current : null);
			tip.AllowTooltipOnNavigationSelect = Object.op_Implicit((Object)(object)val) && (int)val.currentInputSource == 1;
			Refresh();
		}
	}
	internal sealed class LobbyTab : MonoBehaviour
	{
		private HGHeaderNavigationController navigation;

		private GameObject panel;

		private GameObject tab;

		private static bool IsLoadout(Header header, GameObject reference)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)header.headerButton))
			{
				if (!((Object)(object)((Component)header.headerButton).gameObject == (Object)(object)reference) && (!Object.op_Implicit((Object)(object)reference) || !((Component)header.headerButton).transform.IsChildOf(reference.transform)))
				{
					string headerName = header.headerName;
					if (headerName == null)
					{
						return false;
					}
					return headerName.IndexOf("loadout", StringComparison.OrdinalIgnoreCase) >= 0;
				}
				return true;
			}
			return false;
		}

		internal static void Attach()
		{
			CharacterSelectController val = Object.FindObjectOfType<CharacterSelectController>();
			if (Object.op_Implicit((Object)(object)val) && !Object.op_Implicit((Object)(object)((Component)val).GetComponent<LobbyTab>()))
			{
				((Component)val).gameObject.AddComponent<LobbyTab>();
			}
		}

		private void Start()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00bd: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Expected O, but got Unknown
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Expected O, but got Unknown
			CharacterSelectController select = ((Component)this).GetComponent<CharacterSelectController>();
			navigation = ((IEnumerable<HGHeaderNavigationController>)((Component)this).GetComponentsInChildren<HGHeaderNavigationController>(true)).FirstOrDefault((Func<HGHeaderNavigationController, bool>)((HGHeaderNavigationController n) => n.headers != null && n.headers.Any((Header h) => IsLoadout(h, select.loadoutHeaderButton))));
			if (!Object.op_Implicit((Object)(object)navigation))
			{
				Debug.LogWarning((object)"[BetterQueue] Lobby navigation unavailable. F7 editor remains available in a run.");
				Object.Destroy((Object)(object)this);
				return;
			}
			int num = navigation.headers.FindIndex((Header h) => IsLoadout(h, select.loadoutHeaderButton));
			Header val = navigation.headers[num];
			RectTransform val2 = Widgets.Rect(val.headerRoot.transform.parent, "BetterQueue.BuildEditor");
			panel = ((Component)val2).gameObject;
			RectTransform val3 = (RectTransform)val.headerRoot.transform;
			val2.anchorMin = val3.anchorMin;
			val2.anchorMax = val3.anchorMax;
			val2.pivot = val3.pivot;
			val2.sizeDelta = val3.sizeDelta;
			val2.anchoredPosition = val3.anchoredPosition;
			((Component)val2).gameObject.AddComponent<BuildEditor>().Initialize();
			panel.SetActive(false);
			tab = Object.Instantiate<GameObject>(((Component)val.headerButton).gameObject, ((Component)val.headerButton).transform.parent, false);
			((Object)tab).name = "BetterQueue.QueueTab";
			tab.SetActive(true);
			MPButton component = tab.GetComponent<MPButton>();
			((Selectable)component).interactable = true;
			((Button)component).onClick = new ButtonClickedEvent();
			if (Object.op_Implicit((Object)(object)navigation.headerHighlightObject) && navigation.headerHighlightObject.transform.IsChildOf(((Component)val.headerButton).transform))
			{
				Transform val4 = tab.transform.Find(((Object)navigation.headerHighlightObject).name);
				if (Object.op_Implicit((Object)(object)val4))
				{
					Object.Destroy((Object)(object)((Component)val4).gameObject);
				}
			}
			ButtonSkinController[] components = tab.GetComponents<ButtonSkinController>();
			foreach (ButtonSkinController obj in components)
			{
				obj.useRecommendedButtonWidth = false;
				obj.useRecommendedLabel = false;
			}
			LanguageTextMeshController[] componentsInChildren = tab.GetComponentsInChildren<LanguageTextMeshController>(true);
			for (int num2 = 0; num2 < componentsInChildren.Length; num2++)
			{
				((Behaviour)componentsInChildren[num2]).enabled = false;
			}
			ViewableTag[] componentsInChildren2 = tab.GetComponentsInChildren<ViewableTag>(true);
			for (int num2 = 0; num2 < componentsInChildren2.Length; num2++)
			{
				Object.Destroy((Object)(object)componentsInChildren2[num2]);
			}
			TextMeshProUGUI componentInChildren = tab.GetComponentInChildren<TextMeshProUGUI>(true);
			((TMP_Text)componentInChildren).text = "Queue";
			tab.transform.SetSiblingIndex(((Component)val.headerButton).transform.GetSiblingIndex() + 1);
			navigation.headers.Insert(num + 1, new Header
			{
				headerName = "BetterQueue",
				headerButton = component,
				tmpHeaderText = componentInChildren,
				headerRoot = panel,
				AreConsolePlatformsSupported = true,
				isPrimaryPlayerOnly = val.isPrimaryPlayerOnly
			});
			((UnityEvent)((Button)component).onClick).AddListener((UnityAction)delegate
			{
				navigation.ChooseHeader("BetterQueue");
			});
			typeof(HGHeaderNavigationController).GetMethod("RebuildHeaders", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(navigation, null);
			for (int num3 = 0; num3 < navigation.headers.Count; num3++)
			{
				MPButton headerButton = navigation.headers[num3].headerButton;
				if (Object.op_Implicit((Object)(object)headerButton))
				{
					RectTransform val5 = (RectTransform)((Component)headerButton).transform;
					LayoutElement obj2 = ((Component)val5).GetComponent<LayoutElement>() ?? ((Component)val5).gameObject.AddComponent<LayoutElement>();
					obj2.minWidth = 0f;
					obj2.preferredWidth = 0f;
					obj2.flexibleWidth = 1f;
					if (!Object.op_Implicit((Object)(object)((Component)((Transform)val5).parent).GetComponent<LayoutGroup>()))
					{
						Widgets.Place(val5, (float)num3 / (float)navigation.headers.Count, 0f, ((float)num3 + 1f) / (float)navigation.headers.Count, 1f);
					}
					TextMeshProUGUI componentInChildren2 = ((Component)headerButton).GetComponentInChildren<TextMeshProUGUI>(true);
					if (Object.op_Implicit((Object)(object)componentInChildren2))
					{
						((TMP_Text)componentInChildren2).enableAutoSizing = true;
						((TMP_Text)componentInChildren2).fontSizeMin = 12f;
						((TMP_Text)componentInChildren2).fontSizeMax = 20f;
					}
				}
			}
		}

		private void OnDestroy()
		{
			BetterQueuePlugin.Instance?.Store?.Flush();
			if (Object.op_Implicit((Object)(object)navigation) && navigation.headers != null)
			{
				navigation.headers.RemoveAll((Header h) => (Object)(object)h.headerRoot == (Object)(object)panel);
			}
			if (Object.op_Implicit((Object)(object)panel))
			{
				Object.Destroy((Object)(object)panel);
			}
			if (Object.op_Implicit((Object)(object)tab))
			{
				Object.Destroy((Object)(object)tab);
			}
		}
	}
	internal sealed class LoopGlyph : MaskableGraphic
	{
		public override void OnPopulateMesh(VertexHelper mesh)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			mesh.Clear();
			Rect pixelAdjustedRect = ((Graphic)this).GetPixelAdjustedRect();
			float size = Mathf.Min(((Rect)(ref pixelAdjustedRect)).width, ((Rect)(ref pixelAdjustedRect)).height);
			Arc(mesh, ((Rect)(ref pixelAdjustedRect)).center, size, 20f, 160f);
			Arc(mesh, ((Rect)(ref pixelAdjustedRect)).center, size, 200f, 340f);
		}

		private void Arc(VertexHelper mesh, Vector2 center, float size, float start, float end)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_0097: 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_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_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: 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_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: 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)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: 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_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: 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_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			float num = size * 0.35f;
			float num2 = size * 0.055f;
			Vector2 val = default(Vector2);
			Vector2 val2 = default(Vector2);
			for (int i = 0; i < 20; i++)
			{
				float num3 = Mathf.Lerp(start, end, (float)i / 20f) * (MathF.PI / 180f);
				float num4 = Mathf.Lerp(start, end, (float)(i + 1) / 20f) * (MathF.PI / 180f);
				((Vector2)(ref val))..ctor(Mathf.Cos(num3), Mathf.Sin(num3));
				((Vector2)(ref val2))..ctor(Mathf.Cos(num4), Mathf.Sin(num4));
				int currentVertCount = mesh.currentVertCount;
				mesh.AddVert(Vector2.op_Implicit(center + val * (num - num2)), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
				mesh.AddVert(Vector2.op_Implicit(center + val * (num + num2)), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
				mesh.AddVert(Vector2.op_Implicit(center + val2 * (num + num2)), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
				mesh.AddVert(Vector2.op_Implicit(center + val2 * (num - num2)), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
				mesh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2);
				mesh.AddTriangle(currentVertCount, currentVertCount + 2, currentVertCount + 3);
			}
			float num5 = end * (MathF.PI / 180f);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(Mathf.Cos(num5), Mathf.Sin(num5));
			Vector2 val4 = default(Vector2);
			((Vector2)(ref val4))..ctor(0f - val3.y, val3.x);
			Vector2 val5 = center + val3 * num;
			int currentVertCount2 = mesh.currentVertCount;
			mesh.AddVert(Vector2.op_Implicit(val5 + val4 * size * 0.15f), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
			mesh.AddVert(Vector2.op_Implicit(val5 - val4 * size * 0.08f + val3 * size * 0.15f), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
			mesh.AddVert(Vector2.op_Implicit(val5 - val4 * size * 0.08f - val3 * size * 0.15f), Color32.op_Implicit(((Graphic)this).color), Vector4.op_Implicit(Vector2.zero));
			mesh.AddTriangle(currentVertCount2, currentVertCount2 + 1, currentVertCount2 + 2);
		}
	}
	[Serializable]
	public sealed class PlanEntry
	{
		public string id = Guid.NewGuid().ToString("N");

		public string item;

		public string tier;

		public int quantity = 1;

		public PlanEntry Copy()
		{
			return new PlanEntry
			{
				id = id,
				item = item,
				tier = tier,
				quantity = quantity
			};
		}
	}
	[Serializable]
	public sealed class SurvivorPlan
	{
		public string body;

		public List<PlanEntry> entries = new List<PlanEntry>();

		public List<string> repeat = new List<string>();
	}
	[Serializable]
	public sealed class PlanDocument
	{
		public int version = 1;

		public bool legacyImported;

		public List<SurvivorPlan> survivors = new List<SurvivorPlan>();
	}
	public sealed class RunPlan
	{
		private sealed class Step
		{
			internal PlanEntry entry;

			internal int remaining;
		}

		public sealed class Reservation
		{
			private Step step;

			public string Item { get; internal set; }

			internal object Target
			{
				get
				{
					return step;
				}
				set
				{
					step = (Step)value;
				}
			}
		}

		private readonly List<Step> steps = new List<Step>();

		private readonly List<Reservation> pending = new List<Reservation>();

		private readonly Dictionary<string, int> collected = new Dictionary<string, int>();

		private readonly HashSet<string> loops = new HashSet<string>();

		public int PendingCount => pending.Count;

		public void Start(SurvivorPlan plan)
		{
			steps.Clear();
			pending.Clear();
			collected.Clear();
			loops.Clear();
			foreach (string item in plan.repeat)
			{
				loops.Add(item);
			}
			foreach (PlanEntry entry in plan.entries)
			{
				Add(entry);
			}
		}

		private void Add(PlanEntry entry)
		{
			collected.TryGetValue(entry.id, out var value);
			int num = (loops.Contains(entry.tier) ? entry.quantity : Math.Max(0, entry.quantity - value));
			if (num > 0)
			{
				steps.Add(new Step
				{
					entry = entry.Copy(),
					remaining = num
				});
			}
		}

		public void Reconcile(SurvivorPlan plan, string tier)
		{
			steps.RemoveAll((Step s) => s.entry.tier == tier);
			if (plan.repeat.Contains(tier))
			{
				loops.Add(tier);
			}
			else
			{
				loops.Remove(tier);
			}
			foreach (PlanEntry item in plan.entries.Where((PlanEntry e) => e.tier == tier))
			{
				Add(item);
			}
			foreach (Reservation item2 in pending)
			{
				Step old = (Step)item2.Target;
				if (!(old.entry.tier != tier))
				{
					Step step = steps.FirstOrDefault((Step s) => s.entry.id == old.entry.id && s.entry.item == old.entry.item);
					if (step != null)
					{
						item2.Target = step;
					}
				}
			}
		}

		public IEnumerable<PlanEntry> Next(Func<string, bool> usable)
		{
			HashSet<string> tiers = new HashSet<string>();
			foreach (Step step in steps)
			{
				if (usable(step.entry.item))
				{
					int num = pending.Count((Reservation r) => r.Target == step);
					if (step.remaining > num && tiers.Add(step.entry.tier))
					{
						PlanEntry planEntry = step.entry.Copy();
						planEntry.quantity = step.remaining - num;
						yield return planEntry;
					}
				}
			}
		}

		public Reservation Reserve(string entryId)
		{
			Step step = steps.FirstOrDefault((Step s) => s.entry.id == entryId && s.remaining > pending.Count((Reservation r) => r.Target == s));
			if (step == null)
			{
				return null;
			}
			Reservation reservation = new Reservation
			{
				Item = step.entry.item,
				Target = step
			};
			pending.Add(reservation);
			return reservation;
		}

		public void Cancel(Reservation reservation)
		{
			if (reservation != null)
			{
				pending.Remove(reservation);
			}
		}

		public void ClearReservations()
		{
			pending.Clear();
		}

		public bool Collect(string item)
		{
			Reservation reservation = pending.FirstOrDefault((Reservation r) => r.Item == item);
			Step step;
			if (reservation != null)
			{
				pending.Remove(reservation);
				step = (Step)reservation.Target;
				if (!steps.Contains(step))
				{
					return false;
				}
			}
			else
			{
				step = steps.FirstOrDefault((Step s) => s.remaining > 0 && s.entry.item == item);
				if (step == null || steps.FirstOrDefault((Step s) => s.remaining > 0 && s.entry.tier == step.entry.tier) != step)
				{
					return false;
				}
			}
			collected.TryGetValue(step.entry.id, out var value);
			collected[step.entry.id] = value + 1;
			if (--step.remaining == 0)
			{
				if (!loops.Contains(step.entry.tier))
				{
					steps.Remove(step);
				}
				else if (!steps.Any((Step s) => s.entry.tier == step.entry.tier && s.remaining > 0))
				{
					PlanEntry[] array = (from s in steps
						where s.entry.tier == step.entry.tier
						select s.entry.Copy()).ToArray();
					steps.RemoveAll((Step s) => s.entry.tier == step.entry.tier);
					PlanEntry[] array2 = array;
					foreach (PlanEntry planEntry in array2)
					{
						steps.Add(new Step
						{
							entry = planEntry,
							remaining = planEntry.quantity
						});
					}
				}
			}
			return true;
		}

		public int Remaining(string id)
		{
			return steps.Where((Step s) => s.entry.id == id).Sum((Step s) => s.remaining);
		}
	}
	internal static class PlanSaveLocation
	{
		internal static string DirectoryFor(string gameProfile, string localRoot = null)
		{
			if (string.IsNullOrWhiteSpace(gameProfile))
			{
				throw new ArgumentException("A local game profile is required.", "gameProfile");
			}
			string s = gameProfile.Trim();
			using SHA256 sHA = SHA256.Create();
			string path = BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(s))).Replace("-", "").Substring(0, 24);
			return Path.Combine(localRoot ?? Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Modwright", "BetterQueue", path);
		}
	}
	internal sealed class PlanStore
	{
		[Serializable]
		private sealed class LegacyDocument
		{
			public List<LegacyPlan> survivorPlans;
		}

		[Serializable]
		private sealed class LegacyPlan
		{
			public string survivor;

			public List<LegacyEntry> entries;

			public List<string> repeatTiers;
		}

		[Serializable]
		private sealed class LegacyEntry
		{
			public string pickup;

			public int count;
		}

		private readonly string path;

		private readonly string profilePath;

		private bool dirty;

		private float saveAfter;

		private bool damagedPrimary;

		private bool unsupported;

		internal PlanDocument Document { get; private set; }

		internal string Error { get; private set; }

		internal bool IsDirty => dirty;

		internal PlanStore(string configDirectory, string localDirectory)
		{
			profilePath = Path.Combine(configDirectory, "BetterQueue.plans.json");
			path = Path.Combine(localDirectory, "BetterQueue.plans.json");
			Document = Read(path) ?? Read(path + ".bak");
			bool flag = Document == null;
			if (flag)
			{
				Document = Read(profilePa