Decompiled source of CommandQueueRemastered v0.3.2

CommandQueueRemastered.dll

Decompiled 11 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using CommandQueueRemastered.Core;
using CommandQueueRemastered.Game;
using CommandQueueRemastered.Integrations;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RoR2;
using RoR2.Artifacts;
using RoR2.UI;
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("CommandQueueRemastered")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.2.0")]
[assembly: AssemblyInformationalVersion("0.3.2")]
[assembly: AssemblyProduct("CommandQueueRemastered")]
[assembly: AssemblyTitle("CommandQueueRemastered")]
[assembly: AssemblyVersion("0.3.2.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 CommandQueueRemastered
{
	[BepInPlugin("local.commandqueue.remastered", "CommandQueue Remastered", "0.3.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInIncompatibility("com.kuberoot.commandqueuewithsave")]
	[BepInIncompatibility("local.commandqueue.iconfix")]
	[BepInIncompatibility("ProperSave_CommandQueueExtended")]
	public sealed class RemasteredPlugin : BaseUnityPlugin
	{
		public const string Guid = "local.commandqueue.remastered";

		public const string Name = "CommandQueue Remastered";

		public const string Version = "0.3.2";

		internal const float ItemIconBaseSize = 51.2f;

		internal static RemasteredPlugin Instance;

		internal readonly QueueState Queue = new QueueState(ItemGroups.GroupOf);

		internal PresetStore Presets;

		internal readonly Dictionary<string, ConfigEntry<bool>> GroupOptions = new Dictionary<string, ConfigEntry<bool>>(StringComparer.Ordinal);

		internal ConfigEntry<bool> RotateRepeatedItems;

		internal ConfigEntry<float> ItemScale;

		internal ConfigEntry<float> MenuScale;

		internal ConfigEntry<SpecialPickupBehavior> TemporaryItemBehavior;

		internal ConfigEntry<SpecialPickupBehavior> EtherealItemBehavior;

		internal Sprite ModIcon;

		internal Texture2D ModIconTexture;

		private Harmony harmony;

		private ProperSaveAdapter properSave;

		private readonly HashSet<PickupPickerController> pendingSelections = new HashSet<PickupPickerController>();

		private readonly HashSet<PickupPickerController> manualDisplays = new HashSet<PickupPickerController>();

		private static readonly MethodInfo localParticipantGetter = AccessTools.PropertyGetter(typeof(NetworkUIPromptController), "currentLocalParticipant");

		private readonly List<ScoreboardQueueUI> scoreboardViews = new List<ScoreboardQueueUI>();

		private float nextScoreboardScan;

		internal bool presetsReadFailed;

		internal bool SuppressPauseShortcut => scoreboardViews.Any((ScoreboardQueueUI view) => Object.op_Implicit((Object)(object)view) && view.SuppressPauseShortcut);

		private static bool InteractionActive(NetworkUIPromptController prompt, LocalUser user)
		{
			if (Object.op_Implicit((Object)(object)prompt) && user != null)
			{
				return localParticipantGetter.Invoke(prompt, null) == user;
			}
			return false;
		}

		private void Awake()
		{
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Expected O, but got Unknown
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			Instance = this;
			if (new string[3] { "com.kuberoot.commandqueuewithsave", "local.commandqueue.iconfix", "ProperSave_CommandQueueExtended" }.Any(Chainloader.PluginInfos.ContainsKey))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Disable CommandQueueExtended, IconFix and ProperSave_CommandQueueExtended before using Remastered. Remastered initialization stopped to avoid conflicting queue handlers.");
				((Behaviour)this).enabled = false;
				return;
			}
			try
			{
				string[] names = ItemGroups.Names;
				foreach (string text in names)
				{
					GroupOptions.Add(text, ((BaseUnityPlugin)this).Config.Bind<bool>("Groups", text, true, "Enable the " + text + " queue group."));
				}
				RotateRepeatedItems = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RotateRepeatedItems", true, "Move collected repeated items to the queue end. When disabled, keep displayed order and quantities while cycling through every queued item internally.");
				Queue.RotateRepeatedItems = RotateRepeatedItems.Value;
				RotateRepeatedItems.SettingChanged += delegate
				{
					Queue.RotateRepeatedItems = RotateRepeatedItems.Value;
				};
				TemporaryItemBehavior = ((BaseUnityPlugin)this).Config.Bind<SpecialPickupBehavior>("Special items", "TemporaryItemBehavior", SpecialPickupBehavior.ManualMenu, "Behavior for timed temporary Command pickups. ManualMenu: open the normal picker. UseQueueWithoutConsuming: select the tier's current queued item without changing quantities, order or Repeat progress. UseQueueNormally: select and consume normally. Missing or unavailable queued items open the normal picker.");
				EtherealItemBehavior = ((BaseUnityPlugin)this).Config.Bind<SpecialPickupBehavior>("Special items", "EtherealItemBehavior", SpecialPickupBehavior.ManualMenu, "Behavior for ethereal Command pickups. ManualMenu: open the normal picker. UseQueueWithoutConsuming: select the tier's current queued item without changing quantities, order or Repeat progress. UseQueueNormally: select and consume normally. Missing or unavailable queued items open the normal picker.");
				MenuScale = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MenuScale", 1f, new ConfigDescription("Queue menu scale; capped to fit the screen. Default: 1.0x.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
				ItemScale = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ItemScale", 1f, new ConfigDescription("Item button scale. 1.0x uses the compact 51.2-unit base size.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
				Presets = new PresetStore(Path.Combine(Paths.ConfigPath, "commandQueueRemastered.presets.json"));
				try
				{
					Presets.Load();
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Preset file could not be loaded; existing file retained: " + ex));
					presetsReadFailed = true;
				}
				if (!presetsReadFailed)
				{
					try
					{
						int num = Presets.ImportLegacy(Path.Combine(Paths.ConfigPath, "commandQueueSaves.json"));
						if (num > 0)
						{
							((BaseUnityPlugin)this).Logger.LogInfo((object)("Imported " + num + " legacy CommandQueue presets. Source file retained unchanged."));
						}
					}
					catch (Exception ex2)
					{
						((BaseUnityPlugin)this).Logger.LogError((object)("Legacy preset import failed; no presets imported. Import will retry on next startup: " + ex2));
					}
				}
				harmony = new Harmony("local.commandqueue.remastered");
				harmony.PatchAll(typeof(RemasteredPlugin).Assembly);
				LookingGlassCommandCompatibility.Register(harmony, this);
				Run.onRunStartGlobal += OnRunStart;
				Run.onRunDestroyGlobal += OnRunEnd;
				OptionalOptions.Register(this);
				properSave = new ProperSaveAdapter(this);
				properSave.Initialize();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("CommandQueue Remastered 0.3.2 initialized. Interface: game scoreboard. Game: " + Application.version + "."));
			}
			catch (Exception ex3)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Remastered initialization failed: " + ex3));
				OnDestroy();
				((Behaviour)this).enabled = false;
			}
		}

		internal void LogError(string context, Exception exception)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)(context + ": " + exception));
		}

		internal void LogInfo(string message)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		}

		internal void LogWarning(string message)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)message);
		}

		internal bool HasPendingSelection(PickupPickerController picker)
		{
			return pendingSelections.Contains(picker);
		}

		private SpecialPickupBehavior SelectionBehavior(UniquePickup pickup)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return SpecialPickupPolicy.Resolve(((UniquePickup)(ref pickup)).isTempItem, pickup.isRental, TemporaryItemBehavior.Value, EtherealItemBehavior.Value);
		}

		internal bool GroupEnabled(string group)
		{
			if (group != null && GroupOptions.TryGetValue(group, out var value))
			{
				return value.Value;
			}
			return false;
		}

		internal bool BlocksGameplay(LocalUser user)
		{
			return scoreboardViews.Any((ScoreboardQueueUI view) => Object.op_Implicit((Object)(object)view) && view.BlocksGameplay(user));
		}

		private void Update()
		{
			AttachScoreboards();
			properSave?.Update();
		}

		private void AttachScoreboards()
		{
			if (Time.unscaledTime < nextScoreboardScan)
			{
				return;
			}
			nextScoreboardScan = Time.unscaledTime + 0.5f;
			scoreboardViews.RemoveAll((ScoreboardQueueUI view) => !Object.op_Implicit((Object)(object)view));
			HUD[] array = Object.FindObjectsOfType<HUD>();
			foreach (HUD val in array)
			{
				if (!Object.op_Implicit((Object)(object)val.scoreboardPanel))
				{
					continue;
				}
				ScoreboardController componentInChildren = val.scoreboardPanel.GetComponentInChildren<ScoreboardController>(true);
				if (Object.op_Implicit((Object)(object)componentInChildren) && !Object.op_Implicit((Object)(object)((Component)componentInChildren).GetComponent<ScoreboardQueueUI>()))
				{
					ScoreboardQueueUI scoreboardQueueUI = ((Component)componentInChildren).gameObject.AddComponent<ScoreboardQueueUI>();
					try
					{
						scoreboardQueueUI.Initialize(this, val, componentInChildren);
						scoreboardViews.Add(scoreboardQueueUI);
					}
					catch (Exception exception)
					{
						scoreboardQueueUI.DisableAfterFailure();
						LogError("Scoreboard initialization failed", exception);
					}
				}
			}
		}

		private void OnRunStart(Run run)
		{
			Queue.Reset();
			pendingSelections.Clear();
		}

		private void OnRunEnd(Run run)
		{
			Queue.Reset();
			pendingSelections.Clear();
		}

		private void OnDestroy()
		{
			foreach (ScoreboardQueueUI scoreboardView in scoreboardViews)
			{
				if (Object.op_Implicit((Object)(object)scoreboardView))
				{
					Object.Destroy((Object)(object)scoreboardView);
				}
			}
			scoreboardViews.Clear();
			properSave?.Dispose();
			Run.onRunStartGlobal -= OnRunStart;
			Run.onRunDestroyGlobal -= OnRunEnd;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if (Object.op_Implicit((Object)(object)ModIcon))
			{
				Object.Destroy((Object)(object)ModIcon);
			}
			if (Object.op_Implicit((Object)(object)ModIconTexture))
			{
				Object.Destroy((Object)(object)ModIconTexture);
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		internal bool ScheduleSelection(PickupPickerController picker, LocalUser user, NetworkUIPromptController prompt, CameraRigController camera)
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)picker) || manualDisplays.Contains(picker))
			{
				return false;
			}
			if (pendingSelections.Contains(picker))
			{
				return true;
			}
			if (user == null || !Object.op_Implicit((Object)(object)Run.instance) || picker.options == null || !Object.op_Implicit((Object)(object)prompt))
			{
				return false;
			}
			GameObject commandCubePrefab = CommandArtifactManager.commandCubePrefab;
			PickupPickerController val = (Object.op_Implicit((Object)(object)commandCubePrefab) ? commandCubePrefab.GetComponent<PickupPickerController>() : null);
			if (!Object.op_Implicit((Object)(object)val) || (Object)(object)picker.panelPrefab != (Object)(object)val.panelPrefab || picker.isDelusionChoice || picker.isRebirthChoice)
			{
				return false;
			}
			CommandOption[] array = picker.options.Select(delegate(Option option)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_0053: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				PickupDef pickupDef2 = PickupCatalog.GetPickupDef(option.pickup.pickupIndex);
				ItemDef val3 = ((pickupDef2 == null) ? null : ItemCatalog.GetItemDef(pickupDef2.itemIndex));
				return new CommandOption(Object.op_Implicit((Object)(object)val3) ? pickupDef2.internalName : null, Object.op_Implicit((Object)(object)val3) ? ((object)val3.tier/*cast due to .constrained prefix*/).ToString() : null, option.available && Object.op_Implicit((Object)(object)val3) && GroupEnabled(ItemGroups.Group(val3)) && SelectionBehavior(option.pickup) != SpecialPickupBehavior.ManualMenu);
			}).ToArray();
			PickupDef pickupDef = PickupCatalog.GetPickupDef(picker.GetPickupIndex());
			ItemDef val2 = ((pickupDef == null) ? null : ItemCatalog.GetItemDef(pickupDef.itemIndex));
			string text = (Object.op_Implicit((Object)(object)val2) ? ((object)val2.tier/*cast due to .constrained prefix*/).ToString() : null);
			int num = CommandSelection.FindOption(Queue, array, text, ItemGroups.TierOf);
			if (array.Any((CommandOption option) => ItemGroups.GroupOfTier(option.Tier) == "Void"))
			{
				LogInfo("Void command essence: source tier=" + (text ?? "not received") + "; option tiers=" + string.Join(",", (from option in array
					select option.Tier into tier
					where tier != null
					select tier).Distinct()) + "; queue choice=" + ((num < 0) ? "manual menu" : (array[num].Pickup + " (" + array[num].Tier + ")")) + ".");
			}
			if (num < 0)
			{
				return false;
			}
			CommandOption commandOption = array[num];
			SpecialPickupBehavior behavior = SelectionBehavior(picker.options[num].pickup);
			pendingSelections.Add(picker);
			try
			{
				((MonoBehaviour)this).StartCoroutine(SubmitNextFrame(picker, num, commandOption.Pickup, commandOption.Tier, user, prompt, camera, behavior));
			}
			catch
			{
				pendingSelections.Remove(picker);
				throw;
			}
			return true;
		}

		private IEnumerator SubmitNextFrame(PickupPickerController picker, int optionIndex, string pickup, string tier, LocalUser user, NetworkUIPromptController prompt, CameraRigController camera, SpecialPickupBehavior behavior)
		{
			yield return null;
			bool flag = false;
			try
			{
				if (!Object.op_Implicit((Object)(object)picker) || !InteractionActive(prompt, user))
				{
					yield break;
				}
				int num = Queue.FindHead(tier, ItemGroups.TierOf, resetRepeatCycle: false);
				if (num >= 0 && !(Queue.Entries[num].Pickup != pickup) && picker.options != null && optionIndex < picker.options.Length && picker.options[optionIndex].available && !(PickupCatalog.GetPickupDef(picker.options[optionIndex].pickup.pickupIndex)?.internalName != pickup) && SelectionBehavior(picker.options[optionIndex].pickup) == behavior && GroupEnabled(ItemGroups.GroupOf(pickup)))
				{
					if (behavior == SpecialPickupBehavior.UseQueueNormally)
					{
						num = Queue.FindHead(tier, ItemGroups.TierOf);
					}
					picker.SubmitChoice(optionIndex);
					flag = true;
					SpecialPickupPolicy.CompleteSelection(Queue, num, tier, behavior);
				}
			}
			catch (Exception exception)
			{
				LogError("Automatic command selection failed; queue retained where possible", exception);
			}
			finally
			{
				pendingSelections.Remove(picker);
				if (!flag && Object.op_Implicit((Object)(object)picker) && InteractionActive(prompt, user) && Object.op_Implicit((Object)(object)camera))
				{
					manualDisplays.Add(picker);
					try
					{
						AccessTools.Method(typeof(PickupPickerController), "OnDisplayBegin", (Type[])null, (Type[])null).Invoke(picker, new object[3] { prompt, user, camera });
					}
					catch (Exception exception2)
					{
						LogError("Manual command picker fallback failed", exception2);
					}
					finally
					{
						manualDisplays.Remove(picker);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(PickupPickerController), "OnDisplayBegin")]
	internal static class CommandSelectionPatch
	{
		private static bool Prefix(PickupPickerController __instance, NetworkUIPromptController networkUIPromptController, LocalUser localUser, CameraRigController cameraRigController)
		{
			try
			{
				return !(RemasteredPlugin.Instance?.ScheduleSelection(__instance, localUser, networkUIPromptController, cameraRigController) ?? false);
			}
			catch (Exception exception)
			{
				RemasteredPlugin.Instance?.LogError("Command selection hook failed; opening vanilla picker", exception);
				return true;
			}
		}
	}
}
namespace CommandQueueRemastered.Integrations
{
	internal sealed class ItemDescriptions
	{
		private readonly RemasteredPlugin plugin;

		private MethodInfo enhanced;

		private float nextLookup;

		private bool failed;

		private bool reportedMismatch;

		public ItemDescriptions(RemasteredPlugin plugin)
		{
			this.plugin = plugin;
			FindIntegration();
		}

		private void FindIntegration()
		{
			Type type = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
				select assembly.GetType("LookingGlass.ItemStatsNameSpace.ItemStats")).FirstOrDefault((Type candidate) => candidate != null);
			enhanced = type?.GetMethod("GetItemDescription", BindingFlags.Static | BindingFlags.Public, null, new Type[5]
			{
				typeof(ItemDef),
				typeof(int),
				typeof(CharacterMaster),
				typeof(bool),
				typeof(bool)
			}, null);
			if (type != null && enhanced == null && !reportedMismatch)
			{
				reportedMismatch = true;
				plugin.LogWarning("LookingGlass API differs; using vanilla descriptions.");
			}
		}

		public string Get(ItemDef item, CharacterMaster master)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			if (enhanced == null && Time.unscaledTime >= nextLookup)
			{
				nextLookup = Time.unscaledTime + 5f;
				FindIntegration();
			}
			if (enhanced != null && !failed && Object.op_Implicit((Object)(object)master))
			{
				try
				{
					int num = (Object.op_Implicit((Object)(object)master.inventory) ? master.inventory.GetItemCountEffective(item.itemIndex) : 0);
					string text = enhanced.Invoke(null, new object[5] { item, num, master, true, false }) as string;
					if (!string.IsNullOrEmpty(text))
					{
						return text;
					}
				}
				catch (Exception exception)
				{
					failed = true;
					plugin.LogError("LookingGlass description failed; using vanilla descriptions", exception);
				}
			}
			string text2 = Language.GetString(item.descriptionToken);
			if (string.IsNullOrWhiteSpace(text2) || text2 == item.descriptionToken)
			{
				text2 = Language.GetString(item.pickupToken);
			}
			return text2;
		}
	}
	internal static class LookingGlassCommandCompatibility
	{
		private static readonly FieldInfo panelField = AccessTools.Field(typeof(PickupPickerController), "panelInstance");

		internal static void Register(Harmony harmony, RemasteredPlugin plugin)
		{
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			Type type = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
				select assembly.GetType("LookingGlass.CommandWindowBlur.NoWindowBlur")).FirstOrDefault((Type candidate) => candidate != null);
			if (type == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.DeclaredMethod(type, "OnDisplayBegin", new Type[5]
			{
				typeof(Action<PickupPickerController, NetworkUIPromptController, LocalUser, CameraRigController>),
				typeof(PickupPickerController),
				typeof(NetworkUIPromptController),
				typeof(LocalUser),
				typeof(CameraRigController)
			}, (Type[])null);
			if (methodInfo == null || methodInfo.IsStatic || methodInfo.ReturnType != typeof(void) || panelField == null)
			{
				plugin.LogWarning("LookingGlass Command panel API differs; automatic selection compatibility needs verification.");
				return;
			}
			try
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(LookingGlassCommandCompatibility), "GuardMissingPanel", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
				plugin.LogInfo("LookingGlass Command panel compatibility registered for panel-free queue selection.");
			}
			catch (Exception exception)
			{
				plugin.LogError("LookingGlass Command panel compatibility could not be registered", exception);
			}
		}

		private static bool SkipPanelWork(PickupPickerController picker)
		{
			if (Object.op_Implicit((Object)(object)picker) && (Object)(object)RemasteredPlugin.Instance != (Object)null && RemasteredPlugin.Instance.HasPendingSelection(picker))
			{
				object? value = panelField.GetValue(picker);
				return !Object.op_Implicit((Object)((value is GameObject) ? value : null));
			}
			return false;
		}

		private static IEnumerable<CodeInstruction> GuardMissingPanel(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Expected O, but got Unknown
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			int num = list.FindIndex((CodeInstruction code) => code.opcode == OpCodes.Ldfld && object.Equals(code.operand, panelField));
			if (num < 1 || list[num - 1].opcode != OpCodes.Ldarg_2 || !list.Take(num - 1).Any((CodeInstruction code) => code.opcode == OpCodes.Callvirt && code.operand is MethodInfo { Name: "Invoke" } methodInfo && methodInfo.DeclaringType == typeof(Action<PickupPickerController, NetworkUIPromptController, LocalUser, CameraRigController>)))
			{
				throw new InvalidOperationException("LookingGlass Command panel IL differs from the supported layout.");
			}
			int index = num - 1;
			object obj = typeof(ILGenerator).GetMethod("DefineLabel").Invoke(generator, null);
			FieldInfo? field = typeof(CodeInstruction).GetField("labels");
			CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_2, (object)null);
			IList list2 = (IList)field.GetValue(list[index]);
			IList list3 = (IList)field.GetValue(val);
			foreach (object item in list2)
			{
				list3.Add(item);
			}
			list2.Clear();
			list2.Add(obj);
			list.InsertRange(index, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[4]
			{
				val,
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(LookingGlassCommandCompatibility), "SkipPanelWork", (Type[])null, (Type[])null)),
				new CodeInstruction(OpCodes.Brfalse, obj),
				new CodeInstruction(OpCodes.Ret, (object)null)
			});
			return list;
		}
	}
	internal static class OptionalOptions
	{
		public static void Register(RemasteredPlugin plugin)
		{
			Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly candidate) => candidate.GetType("RiskOfOptions.ModSettingsManager") != null);
			if (assembly == null)
			{
				plugin.LogInfo("RiskOfOptions not installed; using BepInEx configuration.");
				return;
			}
			foreach (ConfigEntry<bool> value in plugin.GroupOptions.Values)
			{
				RegisterEntry(plugin, assembly, "CheckBoxOption", "CheckBoxConfig", (ConfigEntryBase)(object)value);
			}
			RegisterEntry(plugin, assembly, "CheckBoxOption", "CheckBoxConfig", (ConfigEntryBase)(object)plugin.RotateRepeatedItems);
			RegisterEntry(plugin, assembly, "SliderOption", "SliderConfig", (ConfigEntryBase)(object)plugin.MenuScale);
			RegisterEntry(plugin, assembly, "SliderOption", "SliderConfig", (ConfigEntryBase)(object)plugin.ItemScale);
			RegisterEntry(plugin, assembly, "ChoiceOption", "ChoiceConfig", (ConfigEntryBase)(object)plugin.TemporaryItemBehavior);
			RegisterEntry(plugin, assembly, "ChoiceOption", "ChoiceConfig", (ConfigEntryBase)(object)plugin.EtherealItemBehavior);
			RegisterIcon(plugin, assembly);
		}

		private static void RegisterEntry(RemasteredPlugin plugin, Assembly assembly, string optionName, string configName, ConfigEntryBase entry)
		{
			try
			{
				object obj = Activator.CreateInstance(assembly.GetType("RiskOfOptions.OptionConfigs." + configName, throwOnError: true));
				Set(obj, "name", entry.Definition.Key);
				Set(obj, "category", entry.Definition.Section);
				Set(obj, "description", entry.Description.Description);
				Set(obj, "restartRequired", false);
				if ((object)entry == plugin.ItemScale)
				{
					Set(obj, "min", 0.5f);
					Set(obj, "max", 2f);
					Set(obj, "formatString", "{0:0.00}x");
				}
				if ((object)entry == plugin.MenuScale)
				{
					Set(obj, "min", 0.5f);
					Set(obj, "max", 2f);
					Set(obj, "formatString", "{0:0.00}x");
				}
				object obj2 = Activator.CreateInstance(assembly.GetType("RiskOfOptions.Options." + optionName, throwOnError: true), entry, obj);
				Type type = assembly.GetType("RiskOfOptions.ModSettingsManager", throwOnError: true);
				MethodInfo? method = type.GetMethod("AddOption", new Type[3]
				{
					assembly.GetType("RiskOfOptions.Options.BaseOption", throwOnError: true),
					typeof(string),
					typeof(string)
				});
				if (method == null)
				{
					throw new MissingMethodException(type.FullName, "AddOption");
				}
				method.Invoke(null, new object[3] { obj2, "local.commandqueue.remastered", "CommandQueue Remastered" });
				plugin.LogInfo("RiskOfOptions registered " + entry.Definition.Key + ".");
			}
			catch (Exception exception)
			{
				plugin.LogError("RiskOfOptions registration failed for " + entry.Definition.Key, exception);
			}
		}

		private static void Set(object configuration, string name, object value)
		{
			FieldInfo? field = configuration.GetType().GetField(name);
			if (field == null)
			{
				throw new MissingFieldException(configuration.GetType().FullName, name);
			}
			field.SetValue(configuration, value);
		}

		private static void RegisterIcon(RemasteredPlugin plugin, Assembly assembly)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0090: 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)
			try
			{
				using Stream stream = typeof(RemasteredPlugin).Assembly.GetManifestResourceStream("CommandQueueRemastered.icon.png");
				if (stream == null)
				{
					plugin.LogWarning("Embedded mod icon is missing.");
					return;
				}
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				plugin.ModIconTexture = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!ImageConversion.LoadImage(plugin.ModIconTexture, memoryStream.ToArray()))
				{
					throw new InvalidDataException("Invalid mod icon PNG.");
				}
				plugin.ModIcon = Sprite.Create(plugin.ModIconTexture, new Rect(0f, 0f, (float)((Texture)plugin.ModIconTexture).width, (float)((Texture)plugin.ModIconTexture).height), new Vector2(0.5f, 0.5f));
				Type type = assembly.GetType("RiskOfOptions.ModSettingsManager", throwOnError: true);
				MethodInfo? method = type.GetMethod("SetModIcon", new Type[3]
				{
					typeof(Sprite),
					typeof(string),
					typeof(string)
				});
				if (method == null)
				{
					throw new MissingMethodException(type.FullName, "SetModIcon");
				}
				method.Invoke(null, new object[3] { plugin.ModIcon, "local.commandqueue.remastered", "CommandQueue Remastered" });
				plugin.LogInfo("RiskOfOptions mod icon registered.");
			}
			catch (Exception exception)
			{
				plugin.LogError("RiskOfOptions mod icon registration failed", exception);
			}
		}
	}
	internal sealed class ProperSaveAdapter : IDisposable
	{
		private const string SaveKey = "local.CommandQueueRemastered.queue.v1";

		private readonly RemasteredPlugin plugin;

		private readonly List<KeyValuePair<EventInfo, Delegate>> subscriptions = new List<KeyValuePair<EventInfo, Delegate>>();

		private QueueDocument pending;

		private float loadedAt;

		public ProperSaveAdapter(RemasteredPlugin plugin)
		{
			this.plugin = plugin;
		}

		public void Initialize()
		{
			Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly candidate) => candidate.GetType("ProperSave.SaveFile") != null);
			if (assembly == null)
			{
				plugin.LogInfo("ProperSave not installed; run queue saving disabled.");
				return;
			}
			try
			{
				Subscribe(assembly.GetType("ProperSave.SaveFile", throwOnError: true), "OnGatherSaveData", Gather);
				Subscribe(assembly.GetType("ProperSave.Loading", throwOnError: true), "OnLoadingEnded", Loaded);
				Run.onRunDestroyGlobal += OnRunEnd;
				plugin.LogInfo("ProperSave integration registered (singleplayer / host).");
			}
			catch (Exception exception)
			{
				Dispose();
				plugin.LogError("ProperSave integration could not initialize", exception);
			}
		}

		private void Subscribe(Type type, string name, Action<object> callback)
		{
			EventInfo eventInfo = type.GetEvent(name, BindingFlags.Static | BindingFlags.Public);
			if (eventInfo == null)
			{
				throw new MissingMemberException(type.FullName, name);
			}
			ParameterInfo[] parameters = eventInfo.EventHandlerType.GetMethod("Invoke").GetParameters();
			if (parameters.Length != 1)
			{
				throw new InvalidOperationException("Unsupported ProperSave event: " + name);
			}
			ParameterExpression parameterExpression = Expression.Parameter(parameters[0].ParameterType);
			InvocationExpression body = Expression.Invoke(Expression.Constant(callback), Expression.Convert(parameterExpression, typeof(object)));
			Delegate obj = Expression.Lambda(eventInfo.EventHandlerType, body, parameterExpression).Compile();
			eventInfo.AddEventHandler(null, obj);
			subscriptions.Add(new KeyValuePair<EventInfo, Delegate>(eventInfo, obj));
		}

		private void Gather(object data)
		{
			try
			{
				if (NetworkServer.active && Object.op_Implicit((Object)(object)Run.instance))
				{
					((Dictionary<string, object>)data)["local.CommandQueueRemastered.queue.v1"] = QueueDocument.Capture(plugin.Queue).Encode();
					plugin.LogInfo("ProperSave captured " + plugin.Queue.Entries.Sum((QueueEntry entry) => entry.Count) + " queued items.");
				}
			}
			catch (Exception exception)
			{
				plugin.LogError("ProperSave queue capture failed", exception);
			}
		}

		private void Loaded(object save)
		{
			pending = null;
			try
			{
				if (save != null && NetworkServer.active)
				{
					string text = save.GetType().GetMethods().Single((MethodInfo candidate) => candidate.Name == "TryGetModdedData" && candidate.IsGenericMethodDefinition && candidate.GetParameters().Length == 1)
						.MakeGenericMethod(typeof(string))
						.Invoke(save, new object[1] { "local.CommandQueueRemastered.queue.v1" }) as string;
					if (string.IsNullOrEmpty(text))
					{
						plugin.LogInfo("ProperSave file contains no Remastered queue.");
						return;
					}
					pending = QueueDocument.Decode(text);
					loadedAt = Time.unscaledTime;
					plugin.LogInfo("ProperSave queue read; waiting for the local player to spawn.");
				}
			}
			catch (Exception exception)
			{
				plugin.LogError("ProperSave queue read failed", exception);
			}
		}

		public void Update()
		{
			if (pending == null)
			{
				return;
			}
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			if (Object.op_Implicit((Object)(object)Run.instance) && Object.op_Implicit((Object)(object)((firstLocalUser != null) ? firstLocalUser.cachedBody : null)) && Time.unscaledTime - loadedAt >= 0.75f)
			{
				QueueDocument queueDocument = pending;
				pending = null;
				try
				{
					List<QueueEntry> list = queueDocument.Queue.Where((QueueEntry entry) => Object.op_Implicit((Object)(object)ItemGroups.Definition(entry.Pickup))).ToList();
					int num = queueDocument.Queue.Except(list).Sum((QueueEntry entry) => entry.Count);
					plugin.Queue.Replace(list, queueDocument.RepeatedTiers);
					plugin.LogInfo("ProperSave restored " + list.Sum((QueueEntry entry) => entry.Count) + " queued items; skipped " + num + " unavailable items.");
					return;
				}
				catch (Exception exception)
				{
					plugin.LogError("ProperSave queue restore failed", exception);
					return;
				}
			}
			if (Time.unscaledTime - loadedAt > 30f)
			{
				pending = null;
				plugin.LogWarning("ProperSave queue restore timed out waiting for a local player.");
			}
		}

		private void OnRunEnd(Run run)
		{
			pending = null;
		}

		public void Dispose()
		{
			foreach (KeyValuePair<EventInfo, Delegate> subscription in subscriptions)
			{
				try
				{
					subscription.Key.RemoveEventHandler(null, subscription.Value);
				}
				catch (Exception exception)
				{
					plugin.LogError("ProperSave event cleanup failed", exception);
				}
			}
			subscriptions.Clear();
			pending = null;
			Run.onRunDestroyGlobal -= OnRunEnd;
		}
	}
}
namespace CommandQueueRemastered.Game
{
	internal static class ItemGroups
	{
		public static readonly string[] Names = new string[9] { "White", "Green", "Red", "Lunar", "Boss", "Void", "Hallowed", "Hex", "Pages" };

		public static string Group(ItemTier tier)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected I4, but got Unknown
			switch ((int)tier)
			{
			case 0:
				return "White";
			case 1:
				return "Green";
			case 2:
				return "Red";
			case 3:
				return "Lunar";
			case 4:
				return "Boss";
			case 6:
			case 7:
			case 8:
			case 9:
				return "Void";
			case 13:
				return "Hex";
			case 12:
				return "Pages";
			case 11:
				return "Hallowed";
			default:
				return null;
			}
		}

		public static string Group(ItemDef item)
		{
			//IL_000b: 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 (!Object.op_Implicit((Object)(object)item))
			{
				return null;
			}
			ItemTierDef itemTierDef = ItemTierCatalog.GetItemTierDef(item.tier);
			if (Object.op_Implicit((Object)(object)itemTierDef) && ((Object)itemTierDef).name.IndexOf("Hallowed", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return "Hallowed";
			}
			return Group(item.tier);
		}

		public static ItemDef Definition(string pickup)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			PickupDef pickupDef = PickupCatalog.GetPickupDef(PickupCatalog.FindPickupIndex(pickup));
			if (pickupDef != null)
			{
				return ItemCatalog.GetItemDef(pickupDef.itemIndex);
			}
			return null;
		}

		public static string TierOf(string pickup)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			ItemDef obj = Definition(pickup);
			if (obj == null)
			{
				return null;
			}
			return ((object)obj.tier/*cast due to .constrained prefix*/).ToString();
		}

		public static string GroupOf(string pickup)
		{
			return Group(Definition(pickup));
		}

		public static string GroupOfTier(string tier)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (!Enum.TryParse<ItemTier>(tier, out ItemTier result))
			{
				return null;
			}
			return Group(result);
		}

		public static string PickupName(ItemDef item)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return PickupCatalog.GetPickupDef(PickupCatalog.FindPickupIndex(item.itemIndex))?.internalName;
		}

		public static bool TryVoidMarkerColor(ItemDef item, out Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected I4, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_0051: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			color = Color.white;
			if (!Object.op_Implicit((Object)(object)item))
			{
				return false;
			}
			ItemTier tier = item.tier;
			ItemTier val;
			switch (tier - 6)
			{
			case 0:
				val = (ItemTier)0;
				break;
			case 1:
				val = (ItemTier)1;
				color = new Color(0.47f, 0.85f, 0.31f);
				break;
			case 2:
				val = (ItemTier)2;
				color = new Color(0.95f, 0.25f, 0.25f);
				break;
			case 3:
				val = (ItemTier)4;
				color = new Color(1f, 0.85f, 0.25f);
				break;
			default:
				return false;
			}
			ItemTierDef itemTierDef = ItemTierCatalog.GetItemTierDef(val);
			if (Object.op_Implicit((Object)(object)itemTierDef))
			{
				color = Color32.op_Implicit(ColorCatalog.GetColor(itemTierDef.colorIndex));
			}
			return true;
		}

		public static IEnumerable<ItemDef> Available(string group)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Run.instance))
			{
				return Enumerable.Empty<ItemDef>();
			}
			return ((IEnumerable<ItemDef>)(object)ItemCatalog.allItemDefs).Where((ItemDef item) => !item.hidden && Group(item) == group && Run.instance.availableItems.Contains(item.itemIndex));
		}
	}
	internal sealed class ItemIconCache : IDisposable
	{
		private readonly RemasteredPlugin plugin;

		private readonly Dictionary<ItemIndex, AsyncOperationHandle<Sprite>> loads = new Dictionary<ItemIndex, AsyncOperationHandle<Sprite>>();

		private readonly HashSet<ItemIndex> reportedFailures = new HashSet<ItemIndex>();

		public ItemIconCache(RemasteredPlugin plugin)
		{
			this.plugin = plugin;
		}

		public Sprite Get(ItemDef item)
		{
			//IL_0018: 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_0092: Invalid comparison between Unknown and I4
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			Sprite icon = item.GetIcon();
			if (Object.op_Implicit((Object)(object)icon))
			{
				return icon;
			}
			if (!loads.TryGetValue(item.itemIndex, out var value))
			{
				try
				{
					AssetReferenceT<Sprite> iconReference = item.GetIconReference();
					if (iconReference == null || !((AssetReference)iconReference).RuntimeKeyIsValid())
					{
						ReportFailure(item, "No valid sprite reference is available.");
						return null;
					}
					value = Addressables.LoadAssetAsync<Sprite>(((AssetReference)iconReference).RuntimeKey);
					loads.Add(item.itemIndex, value);
				}
				catch (Exception ex)
				{
					ReportFailure(item, ex.ToString());
					return null;
				}
			}
			if (!value.IsDone)
			{
				return null;
			}
			if ((int)value.Status == 1 && Object.op_Implicit((Object)(object)value.Result))
			{
				return value.Result;
			}
			ReportFailure(item, value.OperationException?.ToString() ?? "Sprite load returned no result.");
			return null;
		}

		private void ReportFailure(ItemDef item, string reason)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (reportedFailures.Add(item.itemIndex))
			{
				plugin.LogWarning("Could not load item icon for " + ((Object)item).name + ": " + reason);
			}
		}

		public void Dispose()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			foreach (AsyncOperationHandle<Sprite> value in loads.Values)
			{
				if (value.IsValid())
				{
					Addressables.Release<Sprite>(value);
				}
			}
			loads.Clear();
			reportedFailures.Clear();
		}
	}
	[HarmonyPatch]
	internal static class QueueEscapePausePatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.DeclaredMethod(typeof(PauseManager), "TogglePauseScreen", (Type[])null, (Type[])null);
			yield return AccessTools.DeclaredMethod(typeof(PauseManager), "OpenMinimalPauseScreen", (Type[])null, (Type[])null);
			yield return AccessTools.DeclaredMethod(typeof(PauseManager), "ClosePauseScreen", (Type[])null, (Type[])null);
		}

		private static bool Prefix()
		{
			RemasteredPlugin instance = RemasteredPlugin.Instance;
			if (instance == null)
			{
				return true;
			}
			return !instance.SuppressPauseShortcut;
		}
	}
	[HarmonyPatch(typeof(LocalUser), "get_isUIFocused")]
	internal static class MenuFocusPatch
	{
		private static void Postfix(LocalUser __instance, ref bool __result)
		{
			RemasteredPlugin instance = RemasteredPlugin.Instance;
			if (instance != null && instance.BlocksGameplay(__instance))
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(LocalUser), "GetUIPassthrough")]
	internal static class MenuPassthroughPatch
	{
		private static bool Prefix(LocalUser __instance, ref UIInputPassthrough __result)
		{
			RemasteredPlugin instance = RemasteredPlugin.Instance;
			if (instance == null || !instance.BlocksGameplay(__instance))
			{
				return true;
			}
			__result = null;
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerCharacterMasterController), "Update")]
	internal static class MenuBodyInputPatch
	{
		private static readonly MethodInfo suppressButtons = AccessTools.Method(typeof(PlayerCharacterMasterController), "SuppressAllButtonsUntilReleased", (Type[])null, (Type[])null);

		private static bool reportedFailure;

		internal static void SuppressButtons(PlayerCharacterMasterController controller)
		{
			if (!Object.op_Implicit((Object)(object)controller) || reportedFailure)
			{
				return;
			}
			try
			{
				suppressButtons.Invoke(controller, null);
			}
			catch (Exception exception)
			{
				reportedFailure = true;
				RemasteredPlugin.Instance?.LogError("Could not suppress buffered gameplay buttons", exception);
			}
		}

		private static void Postfix(PlayerCharacterMasterController __instance)
		{
			//IL_0057: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			LocalUser val = __instance.networkUser?.localUser;
			RemasteredPlugin instance = RemasteredPlugin.Instance;
			if (instance != null && instance.BlocksGameplay(val))
			{
				SuppressButtons(__instance);
				InputBankTest val2 = (Object.op_Implicit((Object)(object)val.cachedBody) ? val.cachedBody.inputBank : null);
				if (Object.op_Implicit((Object)(object)val2))
				{
					val2.moveVector = Vector3.zero;
					val2.SetRawMoveStates(Vector2.zero);
					((ButtonState)(ref val2.skill1)).PushState(false);
					((ButtonState)(ref val2.skill2)).PushState(false);
					((ButtonState)(ref val2.skill3)).PushState(false);
					((ButtonState)(ref val2.skill4)).PushState(false);
					((ButtonState)(ref val2.interact)).PushState(false);
					((ButtonState)(ref val2.jump)).PushState(false);
					((ButtonState)(ref val2.sprint)).PushState(false);
					((ButtonState)(ref val2.rawSprintInput)).PushState(false);
					((ButtonState)(ref val2.activateEquipment)).PushState(false);
					((ButtonState)(ref val2.activateKeyItem)).PushState(false);
					((ButtonState)(ref val2.ping)).PushState(false);
					((ButtonState)(ref val2.keyItemNextElement)).PushState(false);
					((ButtonState)(ref val2.keyItemPrevElement)).PushState(false);
				}
			}
		}
	}
	internal sealed class ScoreboardQueueUI : MonoBehaviour
	{
		private RemasteredPlugin plugin;

		private HUD hud;

		private ScoreboardController scoreboard;

		private RectTransform root;

		private RectTransform panel;

		private RectTransform queueContent;

		private RectTransform itemContent;

		private RectTransform saveContent;

		private RectTransform marker;

		private RectTransform ghost;

		private ScrollRect queueScroll;

		private ScrollRect itemScroll;

		private ScrollRect descriptionScroll;

		private ScrollRect saveScroll;

		private ScrollRect previewScroll;

		private RectTransform previewContent;

		private RectTransform previewHeader;

		private RectTransform saveActions;

		private RectTransform shortcutHelp;

		private TextMeshProUGUI shortcutClickHelp;

		private TextMeshProUGUI description;

		private TextMeshProUGUI previewTitle;

		private TextMeshProUGUI ghostCount;

		private TextMeshProUGUI repeatLabel;

		private TMP_StyleSheet styleSheet;

		private readonly List<Button> selectedSaveActions = new List<Button>();

		private readonly List<QueuePreviewIcon> previewIcons = new List<QueuePreviewIcon>();

		private Image ghostImage;

		private Image ghostVoidMarker;

		private Image repeatImage;

		private RectTransform clearConfirmation;

		private Button cancelClearButton;

		private CanvasGroup panelInput;

		private CanvasGroup toolbarInput;

		private GameObject selectionBeforeConfirmation;

		private int confirmationEscapeFrame = -1;

		private static readonly Color NeutralActionColor = new Color(0.16f, 0.19f, 0.24f, 1f);

		private static readonly Color RepeatActionColor = new Color(0.19f, 0.32f, 0.23f, 1f);

		private static readonly Color ClearActionColor = new Color(0.34f, 0.19f, 0.2f, 1f);

		private TMP_InputField nameInput;

		private TMP_FontAsset font;

		private ItemIconCache icons;

		private ItemDescriptions descriptions;

		private readonly List<QueueItemButton> tiles = new List<QueueItemButton>();

		private readonly List<QueueItemButton> queuedTiles = new List<QueueItemButton>();

		private readonly List<GameObject> originalChildren = new List<GameObject>();

		private readonly List<bool> originalActive = new List<bool>();

		private readonly Dictionary<Graphic, bool> originalGraphics = new Dictionary<Graphic, bool>();

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

		private MPEventSystem cursorSystem;

		private bool hiddenOriginals;

		private bool queueView;

		private bool dirty = true;

		private bool cursorOwned;

		private bool failed;

		private string group = "White";

		private string renameId;

		private string selectedSaveId;

		private string settingsSignature;

		private ItemDef described;

		private QueuePreset previewPreset;

		private QueueItemButton dragged;

		private int dropBoundary = -1;

		private float nextRefresh;

		private const float Width = 1280f;

		private const float Height = 720f;

		internal bool SuppressPauseShortcut
		{
			get
			{
				if (confirmationEscapeFrame != Time.frameCount)
				{
					if (Object.op_Implicit((Object)(object)clearConfirmation) && ((Component)clearConfirmation).gameObject.activeInHierarchy)
					{
						return Input.GetKeyDown((KeyCode)27);
					}
					return false;
				}
				return true;
			}
		}

		private LocalUser User
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)hud))
				{
					return null;
				}
				return hud.localUserViewer;
			}
		}

		private Camera EventCamera => ((Component)root).GetComponentInParent<Canvas>().rootCanvas.worldCamera;

		private static bool Shift
		{
			get
			{
				if (!Input.GetKey((KeyCode)304))
				{
					return Input.GetKey((KeyCode)303);
				}
				return true;
			}
		}

		private static bool Control
		{
			get
			{
				if (!Input.GetKey((KeyCode)306))
				{
					return Input.GetKey((KeyCode)305);
				}
				return true;
			}
		}

		private QueuePreset SelectedSave => plugin.Presets.Presets.FirstOrDefault((QueuePreset preset) => preset.Id == selectedSaveId);

		public bool BlocksGameplay(LocalUser user)
		{
			if (user != null && user == User && !failed && ((Behaviour)this).isActiveAndEnabled)
			{
				return HUD.IsScoreboardActive(user);
			}
			return false;
		}

		public void Initialize(RemasteredPlugin owner, HUD ownerHud, ScoreboardController controller)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_01d8: 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_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0553: Unknown result type (might be due to invalid IL or missing references)
			//IL_0562: Unknown result type (might be due to invalid IL or missing references)
			//IL_056c: Expected O, but got Unknown
			//IL_059f: Unknown result type (might be due to invalid IL or missing references)
			//IL_06dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0701: Unknown result type (might be due to invalid IL or missing references)
			//IL_0710: Unknown result type (might be due to invalid IL or missing references)
			//IL_071a: Expected O, but got Unknown
			//IL_07ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d4: Expected O, but got Unknown
			//IL_08d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e3: Expected O, but got Unknown
			//IL_0a71: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a80: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a8a: Expected O, but got Unknown
			//IL_0ae1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b40: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b47: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b5e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b78: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cc2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cc7: Unknown result type (might be due to invalid IL or missing references)
			plugin = owner;
			hud = ownerHud;
			scoreboard = controller;
			foreach (Transform item in ((Component)controller).transform)
			{
				Transform val = item;
				originalChildren.Add(((Component)val).gameObject);
				originalActive.Add(((Component)val).gameObject.activeSelf);
			}
			font = (from text in ((Component)controller).GetComponentsInChildren<TextMeshProUGUI>(true)
				select ((TMP_Text)text).font).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset asset) => Object.op_Implicit((Object)(object)asset)));
			if (!Object.op_Implicit((Object)(object)font))
			{
				font = TMP_Settings.defaultFontAsset;
			}
			if (!Object.op_Implicit((Object)(object)font))
			{
				throw new InvalidOperationException("No scoreboard font is available.");
			}
			styleSheet = (from text in ((Component)controller).GetComponentsInChildren<TextMeshProUGUI>(true)
				select ((TMP_Text)text).styleSheet).FirstOrDefault((Func<TMP_StyleSheet, bool>)((TMP_StyleSheet sheet) => Object.op_Implicit((Object)(object)sheet)));
			if (!Object.op_Implicit((Object)(object)styleSheet))
			{
				styleSheet = TMP_Settings.defaultStyleSheet;
			}
			icons = new ItemIconCache(plugin);
			descriptions = new ItemDescriptions(plugin);
			root = Rect("CommandQueueRemastered", ((Component)controller).transform);
			((Component)root).gameObject.AddComponent<LayoutElement>().ignoreLayout = true;
			RectTransform obj = root;
			RectTransform obj2 = root;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			obj2.anchorMax = val2;
			obj.anchorMin = val2;
			root.pivot = new Vector2(0.5f, 0.5f);
			root.sizeDelta = new Vector2(1280f, 720f);
			Canvas obj3 = ((Component)root).gameObject.AddComponent<Canvas>();
			obj3.overrideSorting = true;
			obj3.sortingOrder = 40;
			((Component)root).gameObject.AddComponent<GraphicRaycaster>();
			RectTransform val3 = Box("Views", (Transform)(object)root, new Vector2(0f, 0.96f), Vector2.one);
			toolbarInput = ((Component)val3).gameObject.AddComponent<CanvasGroup>();
			Place(Button((Transform)(object)val3, "Players", delegate
			{
				queueView = false;
				ApplyVisibility();
			}), 0f, 0f, 0.16f, 1f);
			Place(Button((Transform)(object)val3, "Command Queue", delegate
			{
				queueView = true;
				ApplyVisibility();
			}), 0.17f, 0f, 0.42f, 1f);
			TextMeshProUGUI obj4 = Label((Transform)(object)val3, "CommandQueue Remastered 0.3.2", 18f);
			((TMP_Text)obj4).alignment = (TextAlignmentOptions)4097;
			Place(((TMP_Text)obj4).rectTransform, 0.44f, 0f, 1f, 1f);
			panel = Box("Queue panel", (Transform)(object)root, Vector2.zero, new Vector2(1f, 0.95f));
			panelInput = ((Component)panel).gameObject.AddComponent<CanvasGroup>();
			RectTransform val4 = Rect("Groups", (Transform)(object)panel);
			Place(val4, 0.01f, 0.947f, 0.99f, 0.989f);
			for (int num = 0; num < ItemGroups.Names.Length; num++)
			{
				string name = ItemGroups.Names[num];
				RectTransform val5 = Button((Transform)(object)val4, name, delegate
				{
					group = name;
					described = null;
					dirty = true;
					CancelDrag();
				});
				Place(val5, (float)num / 9f, 0f, ((float)num + 0.94f) / 9f, 1f);
				groupButtons.Add(name, ((Component)val5).GetComponent<Button>());
			}
			RectTransform val6 = Rect("Queue actions", (Transform)(object)panel);
			Place(val6, 0.01f, 0.895f, 0.68f, 0.937f);
			RectTransform val7 = Button((Transform)(object)val6, "Repeat", ToggleRepeat);
			repeatLabel = ((Component)val7).GetComponentInChildren<TextMeshProUGUI>();
			repeatImage = ((Component)val7).GetComponent<Image>();
			Place(val7, 0f, 0f, 0.22f, 1f);
			Place(Button((Transform)(object)val6, "Clear group", delegate
			{
				Act(delegate
				{
					plugin.Queue.Replace((from entry in plugin.Queue.Entries
						where ItemGroups.GroupOf(entry.Pickup) != @group
						select entry.Copy()).ToList(), plugin.Queue.RepeatedTiers.ToArray());
				});
			}), 0.23f, 0f, 0.46f, 1f);
			RectTransform obj5 = Button((Transform)(object)val6, "Clear all", OpenClearConfirmation);
			((Graphic)((Component)obj5).GetComponent<Image>()).color = ClearActionColor;
			Place(obj5, 0.47f, 0f, 0.68f, 1f);
			queueScroll = Scroll((Transform)(object)panel, "Queued items", 0.01f, 0.72f, 0.68f, 0.88f, out queueContent);
			GridLayoutGroup obj6 = ((Component)queueContent).gameObject.AddComponent<GridLayoutGroup>();
			obj6.spacing = new Vector2(7f, 7f);
			((LayoutGroup)obj6).padding = new RectOffset(8, 8, 8, 8);
			obj6.constraint = (Constraint)1;
			Fit(queueContent, horizontal: false);
			((Component)queueScroll.horizontalScrollbar).gameObject.SetActive(false);
			queueScroll.viewport.offsetMin = Vector2.zero;
			shortcutHelp = Rect("Queue shortcuts", (Transform)(object)panel);
			TextMeshProUGUI val8 = (shortcutClickHelp = Label((Transform)(object)shortcutHelp, "Left-click: +1  |  Shift-left: +10  |  Ctrl-left: add to front\nRight-click: -1  |  Shift-right: -10  |  Ctrl-right: remove stack", 14f));
			Place(((TMP_Text)val8).rectTransform, 0f, 0f, 0.6f, 1f);
			((TMP_Text)val8).enableWordWrapping = false;
			((TMP_Text)val8).enableAutoSizing = true;
			((TMP_Text)val8).fontSizeMin = 12f;
			((TMP_Text)val8).fontSizeMax = 14f;
			TextMeshProUGUI obj7 = Label((Transform)(object)shortcutHelp, "Drag: whole stack  |  Shift-drag: half  |  Ctrl-drag: one", 14f);
			Place(((TMP_Text)obj7).rectTransform, 0.61f, 0.5f, 1f, 1f);
			((TMP_Text)obj7).alignment = (TextAlignmentOptions)260;
			((TMP_Text)obj7).enableWordWrapping = false;
			((TMP_Text)obj7).enableAutoSizing = true;
			((TMP_Text)obj7).fontSizeMin = 12f;
			((TMP_Text)obj7).fontSizeMax = 14f;
			itemScroll = Scroll((Transform)(object)panel, "Available items", 0.01f, 0.26f, 0.68f, 0.7f, out itemContent);
			((Component)itemScroll.horizontalScrollbar).gameObject.SetActive(false);
			itemScroll.viewport.offsetMin = Vector2.zero;
			GridLayoutGroup obj8 = ((Component)itemContent).gameObject.AddComponent<GridLayoutGroup>();
			obj8.spacing = new Vector2(7f, 7f);
			((LayoutGroup)obj8).padding = new RectOffset(8, 8, 8, 8);
			obj8.constraint = (Constraint)1;
			Fit(itemContent, horizontal: false);
			descriptionScroll = Scroll((Transform)(object)panel, "Description", 0.01f, 0.015f, 0.68f, 0.24f, out var content);
			description = Label((Transform)(object)content, "Hover an item for its description.", 17f);
			((TMP_Text)description).enableWordWrapping = true;
			((TMP_Text)description).overflowMode = (TextOverflowModes)0;
			LayoutElement obj9 = ((Component)description).gameObject.AddComponent<LayoutElement>();
			obj9.minWidth = 0f;
			obj9.preferredWidth = 0f;
			obj9.flexibleWidth = 1f;
			VerticalLayoutGroup obj10 = ((Component)content).gameObject.AddComponent<VerticalLayoutGroup>();
			((LayoutGroup)obj10).padding = new RectOffset(8, 8, 8, 8);
			((HorizontalOrVerticalLayoutGroup)obj10).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj10).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj10).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj10).childForceExpandHeight = false;
			Fit(content, horizontal: false);
			RectTransform val9 = Rect("Preset input", (Transform)(object)panel);
			Place(val9, 0.7f, 0.895f, 0.99f, 0.937f);
			nameInput = InputField((Transform)(object)val9);
			Place(((Component)nameInput).GetComponent<RectTransform>(), 0f, 0f, 0.65f, 1f);
			Place(Button((Transform)(object)val9, "Save / Rename", Save), 0.67f, 0f, 1f, 1f);
			saveScroll = Scroll((Transform)(object)panel, "Presets", 0.7f, 0.075f, 0.99f, 0.88f, out saveContent);
			VerticalLayoutGroup obj11 = ((Component)saveContent).gameObject.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj11).spacing = 4f;
			((LayoutGroup)obj11).padding = new RectOffset(6, 6, 6, 6);
			((HorizontalOrVerticalLayoutGroup)obj11).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj11).childForceExpandHeight = false;
			Fit(saveContent, horizontal: false);
			saveActions = Rect("Selected preset actions", (Transform)(object)panel);
			AddSaveAction("Load", delegate
			{
				Act(delegate
				{
					SelectedSave.Document.ApplyGroups(plugin.Queue, ItemGroups.GroupOf, ItemGroups.GroupOfTier);
				});
			});
			AddSaveAction("Preview", delegate
			{
				previewPreset = SelectedSave;
				UpdatePreview();
			});
			AddSaveAction("Rename", delegate
			{
				renameId = SelectedSave.Id;
				nameInput.text = SelectedSave.Name;
				((Selectable)nameInput).Select();
				nameInput.ActivateInputField();
			});
			AddSaveAction("Delete", delegate
			{
				Act(delegate
				{
					if (plugin.presetsReadFailed)
					{
						throw new InvalidOperationException("Preset writes are disabled after a read failure.");
					}
					plugin.Presets.Delete(SelectedSave.Id);
					selectedSaveId = null;
					renameId = null;
					nameInput.text = "";
					UpdatePreview();
				});
			});
			previewHeader = Rect("Preview header", (Transform)(object)panel);
			Place(previewHeader, 0.7f, 0.335f, 0.99f, 0.377f);
			previewTitle = Label((Transform)(object)previewHeader, "", 16f);
			Place(((TMP_Text)previewTitle).rectTransform, 0f, 0f, 0.72f, 1f);
			Place(Button((Transform)(object)previewHeader, "Close", delegate
			{
				previewPreset = null;
				UpdatePreview();
			}), 0.74f, 0f, 1f, 1f);
			previewScroll = Scroll((Transform)(object)panel, "Preset preview", 0.7f, 0.015f, 0.99f, 0.325f, out previewContent);
			Fit(previewContent, horizontal: false);
			GridLayoutGroup obj12 = ((Component)previewContent).gameObject.AddComponent<GridLayoutGroup>();
			obj12.spacing = new Vector2(6f, 6f);
			((LayoutGroup)obj12).padding = new RectOffset(6, 6, 6, 6);
			obj12.constraint = (Constraint)1;
			UpdatePreview();
			marker = Rect("Insertion marker", (Transform)(object)queueContent);
			((Component)marker).gameObject.AddComponent<LayoutElement>().ignoreLayout = true;
			((Graphic)((Component)marker).gameObject.AddComponent<Image>()).color = new Color(0.8f, 0.55f, 1f);
			((Graphic)((Component)marker).GetComponent<Image>()).raycastTarget = false;
			((Component)marker).gameObject.SetActive(false);
			ghost = Rect("Dragged item", (Transform)(object)root);
			RectTransform obj13 = ghost;
			RectTransform obj14 = ghost;
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			obj14.anchorMax = val2;
			obj13.anchorMin = val2;
			ghost.pivot = new Vector2(0f, 1f);
			ghost.sizeDelta = new Vector2(76f, 76f);
			ghostImage = ((Component)ghost).gameObject.AddComponent<Image>();
			((Graphic)ghostImage).raycastTarget = false;
			RectTransform val10 = Rect("Void tier color", (Transform)(object)ghost);
			Place(val10, 0f, 0.96f, 1f, 1f);
			ghostVoidMarker = ((Component)val10).gameObject.AddComponent<Image>();
			((Graphic)ghostVoidMarker).raycastTarget = false;
			ghostCount = Label((Transform)(object)ghost, "", 20f);
			Place(((TMP_Text)ghostCount).rectTransform, 0f, 0f, 1f, 0.33f);
			((TMP_Text)ghostCount).alignment = (TextAlignmentOptions)514;
			((Component)ghost).gameObject.SetActive(false);
			BuildClearConfirmation();
			plugin.Queue.Changed += MarkDirty;
			ApplyVisibility();
			plugin.LogInfo("Native queue UI attached to scoreboard; UI layer=" + ((Component)root).gameObject.layer + ", canvas=" + ((object)((Component)root).GetComponentInParent<Canvas>().rootCanvas.renderMode/*cast due to .constrained prefix*/).ToString() + ", initial view=Players.");
		}

		internal void DisableAfterFailure()
		{
			failed = true;
			CancelDrag();
			ReleaseCursor();
			RestorePlayers();
			if (Object.op_Implicit((Object)(object)root))
			{
				((Component)root).gameObject.SetActive(false);
			}
			((Behaviour)this).enabled = false;
		}

		private void MarkDirty()
		{
			dirty = true;
		}

		private void OnEnable()
		{
			if (Object.op_Implicit((Object)(object)plugin))
			{
				dirty = true;
				ApplyVisibility();
			}
		}

		private void OnDisable()
		{
			CloseClearConfirmation();
			CancelDrag();
			ReleaseCursor();
			RestorePlayers();
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)plugin))
			{
				plugin.Queue.Changed -= MarkDirty;
			}
			ReleaseCursor();
			RestorePlayers();
			icons?.Dispose();
			if (Object.op_Implicit((Object)(object)root))
			{
				Object.Destroy((Object)(object)((Component)root).gameObject);
			}
		}

		private void RestorePlayers()
		{
			if (!hiddenOriginals)
			{
				return;
			}
			foreach (KeyValuePair<Graphic, bool> originalGraphic in originalGraphics)
			{
				if (Object.op_Implicit((Object)(object)originalGraphic.Key))
				{
					((Behaviour)originalGraphic.Key).enabled = originalGraphic.Value;
				}
			}
			originalGraphics.Clear();
			for (int i = 0; i < originalChildren.Count; i++)
			{
				if (Object.op_Implicit((Object)(object)originalChildren[i]))
				{
					originalChildren[i].SetActive(originalActive[i]);
				}
			}
			hiddenOriginals = false;
		}

		private void HidePlayers()
		{
			foreach (GameObject originalChild in originalChildren)
			{
				if (!Object.op_Implicit((Object)(object)originalChild))
				{
					continue;
				}
				Graphic[] componentsInChildren = originalChild.GetComponentsInChildren<Graphic>(true);
				foreach (Graphic val in componentsInChildren)
				{
					Material material = val.material;
					bool flag = Object.op_Implicit((Object)(object)material) && Object.op_Implicit((Object)(object)material.shader) && ((Object)material.shader).name.IndexOf("blur", StringComparison.OrdinalIgnoreCase) >= 0;
					Transform val2 = ((Component)val).transform;
					while (Object.op_Implicit((Object)(object)val2) && (Object)(object)val2 != (Object)(object)((Component)scoreboard).transform)
					{
						flag |= ((Object)val2).name.IndexOf("blur", StringComparison.OrdinalIgnoreCase) >= 0;
						val2 = val2.parent;
					}
					if (!flag)
					{
						if (!originalGraphics.ContainsKey(val))
						{
							originalGraphics.Add(val, ((Behaviour)val).enabled);
						}
						((Behaviour)val).enabled = false;
					}
				}
			}
		}

		private void ReleaseCursor()
		{
			if (cursorOwned && Object.op_Implicit((Object)(object)cursorSystem))
			{
				TMP_InputField obj = nameInput;
				if (obj != null)
				{
					obj.DeactivateInputField(false);
				}
				GameObject val = ((EventSystem)cursorSystem).currentSelectedGameObject;
				if (Object.op_Implicit((Object)(object)val) && (!val.activeInHierarchy || (Object.op_Implicit((Object)(object)scoreboard) && val.transform.IsChildOf(((Component)scoreboard).transform))))
				{
					val = null;
				}
				((EventSystem)cursorSystem).SetSelectedGameObject(val);
				cursorSystem.cursorOpenerCount = Math.Max(0, cursorSystem.cursorOpenerCount - 1);
				BaseInputModule currentInputModule = ((EventSystem)cursorSystem).currentInputModule;
				if (Object.op_Implicit((Object)(object)currentInputModule) && ((Behaviour)currentInputModule).isActiveAndEnabled)
				{
					currentInputModule.DeactivateModule();
					currentInputModule.ActivateModule();
				}
				((EventSystem)cursorSystem).SetSelectedGameObject(val);
			}
			cursorOwned = false;
			cursorSystem = null;
		}

		private void ApplyVisibility()
		{
			if (!Object.op_Implicit((Object)(object)root))
			{
				return;
			}
			bool flag = !failed && User != null && HUD.IsScoreboardActive(User) && ((Component)this).gameObject.activeInHierarchy;
			bool activeSelf = ((Component)root).gameObject.activeSelf;
			((Component)root).gameObject.SetActive(flag);
			if (flag && !activeSelf)
			{
				dirty = true;
			}
			if (!flag)
			{
				CloseClearConfirmation();
				((Component)panel).gameObject.SetActive(false);
				RestorePlayers();
				ReleaseCursor();
				return;
			}
			if (!cursorOwned && Object.op_Implicit((Object)(object)User.eventSystem))
			{
				cursorSystem = User.eventSystem;
				MPEventSystem obj = cursorSystem;
				int cursorOpenerCount = obj.cursorOpenerCount;
				obj.cursorOpenerCount = cursorOpenerCount + 1;
				cursorOwned = true;
			}
			if (!queueView)
			{
				CloseClearConfirmation();
				((Component)panel).gameObject.SetActive(false);
				RestorePlayers();
				CancelDrag();
				return;
			}
			((Component)panel).gameObject.SetActive(true);
			if (!hiddenOriginals)
			{
				for (int i = 0; i < originalChildren.Count; i++)
				{
					if (Object.op_Implicit((Object)(object)originalChildren[i]))
					{
						originalActive[i] = originalChildren[i].activeSelf;
					}
				}
				hiddenOriginals = true;
			}
			HidePlayers();
		}

		private void Update()
		{
			//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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: 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_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_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: 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_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)plugin) || failed)
			{
				return;
			}
			try
			{
				ApplyVisibility();
				if (!((Component)root).gameObject.activeInHierarchy)
				{
					return;
				}
				if (((Component)clearConfirmation).gameObject.activeSelf && Input.GetKeyDown((KeyCode)27))
				{
					confirmationEscapeFrame = Time.frameCount;
					CloseClearConfirmation();
				}
				RectTransform component = ((Component)((Component)root).GetComponentInParent<Canvas>().rootCanvas).GetComponent<RectTransform>();
				float[] obj = new float[3]
				{
					plugin.MenuScale.Value,
					0f,
					0f
				};
				Rect rect = component.rect;
				obj[1] = (((Rect)(ref rect)).width - 20f) / 1280f;
				rect = component.rect;
				obj[2] = (((Rect)(ref rect)).height - 20f) / 720f;
				float num = Mathf.Max(0.1f, Mathf.Min(obj));
				((Transform)root).localScale = Vector3.one * num;
				if (!((Component)panel).gameObject.activeSelf)
				{
					return;
				}
				UpdateQueueLayout();
				string text = string.Join(",", ItemGroups.Names.Where(plugin.GroupEnabled)) + ":" + plugin.ItemScale.Value;
				if (text != settingsSignature)
				{
					dirty = true;
					settingsSignature = text;
				}
				if (Object.op_Implicit((Object)(object)dragged))
				{
					if (RectTransformUtility.RectangleContainsScreenPoint(queueScroll.viewport, Vector2.op_Implicit(Input.mousePosition), EventCamera))
					{
						rect = queueContent.rect;
						float height = ((Rect)(ref rect)).height;
						rect = queueScroll.viewport.rect;
						if (height > ((Rect)(ref rect)).height)
						{
							Vector2 val = default(Vector2);
							RectTransformUtility.ScreenPointToLocalPointInRectangle(queueScroll.viewport, Vector2.op_Implicit(Input.mousePosition), EventCamera, ref val);
							rect = queueScroll.viewport.rect;
							float num2 = Mathf.Min(24f, ((Rect)(ref rect)).height / 4f);
							float y = val.y;
							rect = queueScroll.viewport.rect;
							int num3;
							if (!(y > ((Rect)(ref rect)).yMax - num2))
							{
								float y2 = val.y;
								rect = queueScroll.viewport.rect;
								num3 = ((y2 < ((Rect)(ref rect)).yMin + num2) ? (-1) : 0);
							}
							else
							{
								num3 = 1;
							}
							float num4 = num3;
							queueScroll.verticalNormalizedPosition = Mathf.Clamp01(queueScroll.verticalNormalizedPosition + num4 * Time.unscaledDeltaTime);
						}
					}
					UpdateDrag(Vector2.op_Implicit(Input.mousePosition));
				}
				if (Time.unscaledTime < nextRefresh)
				{
					return;
				}
				nextRefresh = Time.unscaledTime + 0.2f;
				if (dirty && !Object.op_Implicit((Object)(object)dragged))
				{
					Rebuild();
					dirty = false;
				}
				QueueItemButton[] array = tiles.ToArray();
				foreach (QueueItemButton queueItemButton in array)
				{
					if (Object.op_Implicit((Object)(object)queueItemButton) && Object.op_Implicit((Object)(object)queueItemButton.Item))
					{
						queueItemButton.Refresh();
					}
				}
				foreach (QueuePreviewIcon previewIcon in previewIcons)
				{
					if (Object.op_Implicit((Object)(object)previewIcon))
					{
						previewIcon.Refresh();
					}
				}
				UpdateDescription();
			}
			catch (Exception exception)
			{
				failed = true;
				CancelDrag();
				ReleaseCursor();
				RestorePlayers();
				if (Object.op_Implicit((Object)(object)root))
				{
					((Component)root).gameObject.SetActive(false);
				}
				plugin.LogError("Native scoreboard queue failed; queue view disabled and player overview restored", exception);
			}
		}

		private void Rebuild()
		{
			//IL_01c0: 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_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_0416: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_0520: Unknown result type (might be due to invalid IL or missing references)
			//IL_0519: Unknown result type (might be due to invalid IL or missing references)
			Canvas.ForceUpdateCanvases();
			if (!plugin.GroupEnabled(group))
			{
				group = ItemGroups.Names.FirstOrDefault(plugin.GroupEnabled) ?? "";
			}
			foreach (KeyValuePair<string, Button> groupButton in groupButtons)
			{
				((Component)groupButton.Value).gameObject.SetActive(plugin.GroupEnabled(groupButton.Key));
				((Selectable)groupButton.Value).interactable = groupButton.Key != group;
			}
			foreach (QueueItemButton tile in tiles)
			{
				if (Object.op_Implicit((Object)(object)tile))
				{
					((Component)tile).gameObject.SetActive(false);
					Object.Destroy((Object)(object)((Component)tile).gameObject);
				}
			}
			tiles.Clear();
			queuedTiles.Clear();
			foreach (QueueEntry entry in plugin.Queue.Entries)
			{
				ItemDef val = ItemGroups.Definition(entry.Pickup);
				if (Object.op_Implicit((Object)(object)val) && ItemGroups.Group(val) == group)
				{
					queuedTiles.Add(CreateTile(queueContent, val, entry));
				}
			}
			GridLayoutGroup component = ((Component)itemContent).GetComponent<GridLayoutGroup>();
			float num = 51.2f * plugin.ItemScale.Value;
			component.cellSize = Vector2.one * num;
			Rect rect = itemScroll.viewport.rect;
			component.constraintCount = Math.Max(1, (int)((((Rect)(ref rect)).width - 16f) / (num + 7f)));
			GridLayoutGroup component2 = ((Component)queueContent).GetComponent<GridLayoutGroup>();
			component2.cellSize = component.cellSize;
			component2.constraintCount = component.constraintCount;
			foreach (ItemDef item in ItemGroups.Available(group))
			{
				CreateTile(itemContent, item, null);
			}
			foreach (Transform item2 in (Transform)saveContent)
			{
				((Component)item2).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)item2).gameObject);
			}
			if (SelectedSave == null)
			{
				selectedSaveId = null;
			}
			foreach (QueuePreset preset in plugin.Presets.Presets)
			{
				RectTransform obj = Button((Transform)(object)saveContent, "", delegate
				{
					SelectSave(preset.Id);
				});
				((Object)obj).name = "Preset " + preset.Name;
				((Component)obj).gameObject.AddComponent<LayoutElement>().preferredHeight = 48f;
				((Graphic)((Component)obj).GetComponent<Image>()).color = ((preset.Id == selectedSaveId) ? new Color(0.27f, 0.32f, 0.42f, 1f) : new Color(0.12f, 0.15f, 0.21f, 1f));
				TextMeshProUGUI componentInChildren = ((Component)obj).GetComponentInChildren<TextMeshProUGUI>();
				((TMP_Text)componentInChildren).text = "<noparse>" + preset.Name + "</noparse>\n<size=13>" + PresetTotals(preset) + "</size>";
				((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)4097;
				((TMP_Text)componentInChildren).rectTransform.offsetMin = new Vector2(6f, 0f);
				((TMP_Text)componentInChildren).rectTransform.offsetMax = new Vector2(-6f, 0f);
			}
			foreach (Button selectedSaveAction in selectedSaveActions)
			{
				((Selectable)selectedSaveAction).interactable = SelectedSave != null;
			}
			UpdatePreview();
			string[] array = (from item in ItemGroups.Available(@group)
				select ((object)item.tier/*cast due to .constrained prefix*/).ToString()).Distinct().ToArray();
			bool flag = array.Length != 0 && array.All(plugin.Queue.IsRepeated);
			((TMP_Text)repeatLabel).text = (flag ? "Repeat: on" : "Repeat: off");
			((Graphic)repeatImage).color = (flag ? RepeatActionColor : NeutralActionColor);
			if (((Component)clearConfirmation).gameObject.activeSelf)
			{
				return;
			}
			LocalUser user = User;
			if (Object.op_Implicit((Object)(object)((user != null) ? user.eventSystem : null)) && tiles.Count > 0)
			{
				GameObject currentSelectedGameObject = ((EventSystem)User.eventSystem).currentSelectedGameObject;
				if (!Object.op_Implicit((Object)(object)currentSelectedGameObject) || !currentSelectedGameObject.transform.IsChildOf((Transform)(object)root))
				{
					((EventSystem)User.eventSystem).SetSelectedGameObject(((Component)tiles[0]).gameObject);
				}
			}
		}

		private void UpdateQueueLayout()
		{
			//IL_0035: 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_008f: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			float num = 51.2f * plugin.ItemScale.Value;
			float num2 = 2f * num + 7f + 16f;
			Rect rect = panel.rect;
			float num3 = 0.88f - num2 / ((Rect)(ref rect)).height;
			Place(((Component)queueScroll).GetComponent<RectTransform>(), 0.01f, num3, 0.68f, 0.88f);
			float num4 = Mathf.Ceil(((TMP_Text)shortcutClickHelp).preferredHeight);
			RectTransform rect2 = shortcutHelp;
			float num5 = 4f + num4;
			rect = panel.rect;
			float y = num3 - num5 / ((Rect)(ref rect)).height;
			rect = panel.rect;
			Place(rect2, 0.015f, y, 0.68f, num3 - 4f / ((Rect)(ref rect)).height);
			RectTransform component = ((Component)itemScroll).GetComponent<RectTransform>();
			float num6 = 8f + num4;
			rect = panel.rect;
			Place(component, 0.01f, 0.26f, 0.68f, num3 - num6 / ((Rect)(ref rect)).height);
		}

		private QueueItemButton CreateTile(RectTransform parent, ItemDef item, QueueEntry entry)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = Rect("Item " + ((Object)item).name, (Transform)(object)parent);
			val.sizeDelta = Vector2.one * (51.2f * plugin.ItemScale.Value);
			Image val2 = ((Component)val).gameObject.AddComponent<Image>();
			((Graphic)val2).color = new Color(0.12f, 0.15f, 0.21f, 1f);
			QueueItemButton queueItemButton = ((Component)val).gameObject.AddComponent<QueueItemButton>();
			((Selectable)queueItemButton).targetGraphic = (Graphic)(object)val2;
			RectTransform obj = Rect("Icon", (Transform)(object)val);
			Stretch(obj);
			obj.offsetMin = new Vector2(4f, 4f);
			obj.offsetMax = new Vector2(-4f, -4f);
			Image val3 = ((Component)obj).gameObject.AddComponent<Image>();
			((Graphic)val3).raycastTarget = false;
			val3.preserveAspect = true;
			AddVoidMarker((Transform)(object)val, item);
			TextMeshProUGUI val4 = Label((Transform)(object)val, "", 18f);
			Place(((TMP_Text)val4).rectTransform, 0f, 0f, 1f, 0.32f);
			((TMP_Text)val4).alignment = (TextAlignmentOptions)1028;
			queueItemButton.Initialize(this, item, entry, val3, val4);
			tiles.Add(queueItemButton);
			return queueItemButton;
		}

		private void Save()
		{
			Act(delegate
			{
				if (plugin.presetsReadFailed)
				{
					throw new InvalidOperationException("Preset writes are disabled after a read failure.");
				}
				if (renameId == null)
				{
					plugin.Presets.Add(nameInput.text, plugin.Queue);
				}
				else
				{
					plugin.Presets.Rename(renameId, nameInput.text);
				}
				renameId = null;
				nameInput.text = "";
			});
		}

		private void BuildClearConfirmation()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			clearConfirmation = Box("Clear all confirmation", (Transform)(object)root, Vector2.zero, Vector2.one);
			((Graphic)((Component)clearConfirmation).GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.65f);
			RectTransform parent = Box("Confirmation", (Transform)(object)clearConfirmation, new Vector2(0.28f, 0.36f), new Vector2(0.72f, 0.64f));
			TextMeshProUGUI obj = Label((Transform)(object)parent, "Clear all queues?", 22f);
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			Place(((TMP_Text)obj).rectTransform, 0.04f, 0.65f, 0.96f, 0.93f);
			TextMeshProUGUI obj2 = Label((Transform)(object)parent, "All queued items will be removed.", 17f);
			((TMP_Text)obj2).alignment = (TextAlignmentOptions)514;
			Place(((TMP_Text)obj2).rectTransform, 0.04f, 0.39f, 0.96f, 0.64f);
			RectTransform val = Button((Transform)(object)parent, "Cancel", CloseClearConfirmation);
			cancelClearButton = ((Component)val).GetComponent<Button>();
			Place(val, 0.53f, 0.08f, 0.94f, 0.3f);
			RectTransform obj3 = Button((Transform)(object)parent, "Clear all", delegate
			{
				CloseClearConfirmation();
				Act(plugin.Queue.Clear);
			});
			((Graphic)((Component)obj3).GetComponent<Image>()).color = ClearActionColor;
			Place(obj3, 0.06f, 0.08f, 0.47f, 0.3f);
			((Component)clearConfirmation).gameObject.SetActive(false);
		}

		private void OpenClearConfirmation()
		{
			CancelDrag();
			LocalUser user = User;
			selectionBeforeConfirmation = (Object.op_Implicit((Object)(object)((user != null) ? user.eventSystem : null)) ? ((EventSystem)User.eventSystem).currentSelectedGameObject : null);
			nameInput.DeactivateInputField(false);
			CanvasGroup obj = panelInput;
			bool interactable = (toolbarInput.interactable = false);
			obj.interactable = interactable;
			CanvasGroup obj2 = panelInput;
			interactable = (toolbarInput.blocksRaycasts = false);
			obj2.blocksRaycasts = interactable;
			((Transform)clearConfirmation).SetAsLastSibling();
			((Component)clearConfirmation).gameObject.SetActive(true);
			LocalUser user2 = User;
			if (Object.op_Implicit((Object)(object)((user2 != null) ? user2.eventSystem : null)))
			{
				((EventSystem)User.eventSystem).SetSelectedGameObject(((Component)cancelClearButton).gameObject);
			}
		}

		private void CloseClearConfirmation()
		{
			if (Object.op_Implicit((Object)(object)clearConfirmation) && ((Component)clearConfirmation).gameObject.activeSelf)
			{
				((Component)clearConfirmation).gameObject.SetActive(false);
				CanvasGroup obj = panelInput;
				bool interactable = (toolbarInput.interactable = true);
				obj.interactable = interactable;
				CanvasGroup obj2 = panelInput;
				interactable = (toolbarInput.blocksRaycasts = true);
				obj2.blocksRaycasts = interactable;
				LocalUser user = User;
				if (Object.op_Implicit((Object)(object)((user != null) ? user.eventSystem : null)))
				{
					((EventSystem)User.eventSystem).SetSelectedGameObject((Object.op_Implicit((Object)(object)selectionBeforeConfirmation) && selectionBeforeConfirmation.activeInHierarchy) ? selectionBeforeConfirmation : null);
				}
				selectionBeforeConfirmation = null;
			}
		}

		private void ToggleRepeat()
		{
			Act(delegate
			{
				string[] array = (from item in ItemGroups.Available(@group)
					select ((object)item.tier/*cast due to .constrained prefix*/).ToString()).Distinct().ToArray();
				bool flag = array.Length != 0 && array.All(plugin.Queue.IsRepeated);
				string[] array2 = array;
				foreach (string tier in array2)
				{
					if (plugin.Queue.IsRepeated(tier) == flag)
					{
						plugin.Queue.ToggleRepeat(tier);
					}
				}
			});
		}

		private void Act(Action action)
		{
			try
			{
				action();
				dirty = true;
			}
			catch (Exception exception)
			{
				plugin.LogError("Scoreboard queue action failed", exception);
			}
		}

		private void UpdatePreview()
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: 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_021a: 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)
			if (previewPreset != null)
			{
				previewPreset = plugin.Presets.Presets.FirstOrDefault((QueuePreset preset) => preset.Id == previewPreset.Id);
			}
			bool flag = previewPreset != null;
			((Component)previewHeader).gameObject.SetActive(flag);
			((Component)previewScroll).gameObject.SetActive(flag);
			Place(((Component)saveScroll).GetComponent<RectTransform>(), 0.7f, flag ? 0.445f : 0.075f, 0.99f, 0.88f);
			Place(saveActions, 0.7f, flag ? 0.393f : 0.023f, 0.99f, flag ? 0.435f : 0.065f);
			foreach (Transform item in (Transform)previewContent)
			{
				((Component)item).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
			previewIcons.Clear();
			if (!flag)
			{
				return;
			}
			((TMP_Text)previewTitle).text = "<noparse>" + previewPreset.Name + "</noparse>";
			previewScroll.verticalNormalizedPosition = 1f;
			GridLayoutGroup component = ((Component)previewContent).GetComponent<GridLayoutGroup>();
			float num = 38.4f * plugin.ItemScale.Value;
			component.cellSize = Vector2.one * num;
			Rect rect = previewScroll.viewport.rect;
			component.constraintCount = Math.Max(1, (int)((((Rect)(ref rect)).width - 12f) / (num + 6f)));
			foreach (QueueEntry item2 in previewPreset.Document.Queue)
			{
				RectTransform val2 = Box("Preview item " + item2.Pickup, (Transform)(object)previewContent, Vector2.zero, Vector2.one);
				RectTransform obj = Rect("Icon", (Transform)(object)val2);
				Stretch(obj);
				obj.offsetMin = new Vector2(3f, 3f);
				obj.offsetMax = new Vector2(-3f, -3f);
				Image val3 = ((Component)obj).gameObject.AddComponent<Image>();
				val3.preserveAspect = true;
				((Graphic)val3).raycastTarget = false;
				AddVoidMarker((Transform)(object)val2, ItemGroups.Definition(item2.Pickup));
				TextMeshProUGUI obj2 = Label((Transform)(object)val2, "×" + item2.Count, 16f);
				Place(((TMP_Text)obj2).rectTransform, 0f, 0f, 1f, 0.35f);
				((TMP_Text)obj2).alignment = (TextAlignmentOptions)1028;
				QueuePreviewIcon queuePreviewIcon = ((Component)val2).gameObject.AddComponent<QueuePreviewIcon>();
				queuePreviewIcon.Initialize(this, ItemGroups.Definition(item2.Pickup), val3);
				previewIcons.Add(queuePreviewIcon);
				if (!Object.op_Implicit((Object)(object)ItemGroups.Definition(item2.Pickup)))
				{
					TextMeshProUGUI obj3 = Label((Transform)(object)val2, "?", 24f);
					Stretch(((TMP_Text)obj3).rectTransform);
					((TMP_Text)obj3).alignment = (TextAlignmentOptions)514;
				}
			}
		}

		private void AddSaveAction(string text, Action action)
		{
			int count = selectedSaveActions.Count;
			RectTransform val = Button((Transform)(object)saveActions, text, delegate
			{
				if (SelectedSave != null)
				{
					action();
				}
			});
			Place(val, (float)count / 4f, 0f, ((float)count + 0.96f) / 4f, 1f);
			selectedSaveActions.Add(((Component)val).GetComponent<Button>());
		}

		private void SelectSave(string id)
		{
			selectedSaveId = id;
			renameId = null;
			nameInput.text = "";
			dirty = true;
			if (previewPreset != null)
			{
				previewPreset = SelectedSave;
				UpdatePreview();
			}
		}

		private static string PresetTotals(QueuePreset preset)
		{
			//IL_0086: 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)
			List<QueueEntry> queue = preset.Document.Queue;
			List<string> list = new List<string>();
			string[] names = ItemGroups.Names;
			foreach (string name in names)
			{
				QueueEntry[] array = queue.Where((QueueEntry entry) => ItemGroups.GroupOf(entry.Pickup) == name).ToArray();
				long num = ((IEnumerable<QueueEntry>)array).Sum((Func<QueueEntry, long>)((QueueEntry entry) => entry.Count));
				if (num != 0L)
				{
					ItemTierDef itemTierDef = ItemTierCatalog.GetItemTierDef(ItemGroups.Definition(array[0].Pickup).tier);
					string text = (Object.op_Implicit((Object)(object)itemTierDef) ? ColorCatalog.GetColorHexString(itemTierDef.colorIndex) : "FFFFFF");
					list.Add("<color=#" + text + ">" + num + "</color>");
				}
			}
			long num2 = ((IEnumerable<QueueEntry>)queue).Sum((Func<QueueEntry, long>)((QueueEntry entry) => entry.Count));
			if (num2 > 0)
			{
				list.Add("Total " + num2);
			}
			return string.Join("  ", list);
		}

		internal void Describe(ItemDef item)
		{
			if ((Object)(object)described != (Object)(object)item)
			{
				described = item;
				descriptionScroll.verticalNormalizedPosition = 1f;
			}
			UpdateDescription();
		}

		private void UpdateDescription()
		{
			if (Object.op_Implicit((Object)(object)described))
			{
				TextMeshProUGUI obj = description;
				string text = Language.GetString(described.nameToken);
				ItemDescriptions itemDescriptions = descriptions;
				ItemDef item = described;
				LocalUser user = User;
				((TMP_Text)obj).text = "<b>" + text + "</b>\n" + DescriptionFormatting.ForTmp(itemDescriptions.Get(item, (user != null) ? user.cachedMaster : null));
			}
		}

		internal void ScrollDescription(PointerEventData data, bool queued)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Canvas.ForceUpdateCanvases();
			Rect rect = descriptionScroll.content.rect;
			float height = ((Rect)(ref rect)).height;
			rect = descriptionScroll.viewport.rect;
			if (height > ((Rect)(ref rect)).height)
			{
				descriptionScroll.OnScroll(data);
			}
			else if (queued)
			{
				queueScroll.OnScroll(data);
			}
			else
			{
				itemScroll.OnScroll(data);
			}
		}

		internal void Click(QueueItemButton tile, InputButton button)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Describe(tile.Item);
			Act(delegate
			{
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Invalid comparison between Unknown and I4
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				int num = plugin.Queue.Entries.ToList().IndexOf(tile.Entry);
				if ((int)button == 1)
				{
					if (num >= 0)
					{
						plugin.Queue.RemoveQuantity(num, QueueInteraction.DecreaseCount(tile.Entry.Count, Shift, Control));
					}
				}
				else if ((int)button == 0)
				{
					if (num >= 0 && !Control)
					{
						plugin.Queue.Increase(num, QueueInteraction.ClickCount(Shift));
					}
					else
					{
						plugin.Queue.Enqueue(ItemGroups.PickupName(tile.Item), QueueInteraction.ClickCount(Shift), Control);
					}
				}
			});
		}

		internal Sprite Sprite(ItemDef item)
		{
			return icons.Get(item);
		}

		internal void ScrollPreview(PointerEventData data)
		{
			previewScroll.OnScroll(data);
		}

		internal int Count(ItemDef item)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			LocalUser user = User;
			if (!Object.op_Implicit((Object)(object)((user != null) ? user.cachedMaster : null)) || !Object.op_Implicit((Object)(object)User.cachedMaster.inventory))
			{
				return 0;
			}
			return User.cachedMaster.inventory.GetItemCountPermanent(item.itemIndex);
		}

		internal void BeginDrag(QueueItemButton tile, PointerEventData data)
		{
			//IL_0009: 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)
			if (tile.Entry != null && (int)data.button == 0)
			{
				dragged = tile;
				ghostImage.sprite = icons.Get(tile.Item);
				((Component)ghost).gameObject.SetActive(true);
				UpdateDrag(data.position);
			}
		}

		internal void UpdateDrag(Vector2 pointer)
		{
			//IL_0068: 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_0088: 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_00f7: 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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			//IL_0222: 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_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)dragged))
			{
				return;
			}
			ghostImage.sprite = icons.Get(dragged.Item);
			Color color;
			bool flag = ItemGroups.TryVoidMarkerColor(dragged.Item, out color);
			((Component)ghostVoidMarker).gameObject.SetActive(flag);
			if (flag)
			{
				((Graphic)ghostVoidMarker).color = color;
			}
			Vector2 val = default(Vector2);
			RectTransformUtility.ScreenPointToLocalPointInRectangle(root, pointer, EventCamera, ref val);
			ghost.anchoredPosition = val + new Vector2(18f, -18f);
			((TMP_Text)ghostCount).text = "×" + QueueInteraction.DragCount(dragged.Entry.Count, Shift, Control);
			dropBoundary = -1;
			((Component)marker).gameObject.SetActive(false);
			if (!RectTransformUtility.RectangleContainsScreenPoint(queueScroll.viewport, pointer, EventCamera))
			{
				return;
			}
			Vector2 val2 = default(Vector2);
			RectTransformUtility.ScreenPointToLocalPointInRectangle(queueContent, pointer, EventCamera, ref val2);
			if (queuedTiles.Count == 0)
			{
				return;
			}
			GridLayoutGroup component = ((Component)queueContent).GetComponent<GridLayoutGroup>();
			int count = queuedTiles.Count;
			int constraintCount = component.constraintCount;
			float x = component.cellSize.x;
			float x2 = component.spacing.x;
			float