Decompiled source of ThreeChoiceChests v1.0.2

ThreeChoiceChests.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using On.RoR2;
using RoR2;
using RoR2.UI;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
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("ThreeChoiceChests")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("ThreeChoiceChests")]
[assembly: AssemblyTitle("ThreeChoiceChests")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[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 ExamplePlugin
{
	internal static class Log
	{
		private static ManualLogSource _logSource;

		internal static void Init(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		private static string Format(object data, string file, int line)
		{
			string fileName = Path.GetFileName(file);
			return $"[{fileName}:{line}] {data}";
		}

		internal static void Debug(object data, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0)
		{
			_logSource.LogDebug((object)Format(data, file, line));
		}

		internal static void Error(object data, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0)
		{
			_logSource.LogError((object)Format(data, file, line));
		}

		internal static void Fatal(object data, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0)
		{
			_logSource.LogFatal((object)Format(data, file, line));
		}

		internal static void Info(object data, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0)
		{
			_logSource.LogInfo((object)Format(data, file, line));
		}

		internal static void Message(object data, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0)
		{
			_logSource.LogMessage((object)Format(data, file, line));
		}

		internal static void Warning(object data, [CallerFilePath] string file = "", [CallerLineNumber] int line = 0)
		{
			_logSource.LogWarning((object)Format(data, file, line));
		}
	}
}
namespace ThreeChoiceChests
{
	internal sealed class ChoicePanelState
	{
		private struct SelectableState
		{
			internal Selectable selectable;

			internal bool interactable;

			internal Navigation navigation;
		}

		private struct BehaviourState
		{
			internal Behaviour behaviour;

			internal bool enabled;
		}

		internal readonly PickupPickerPanel panel;

		private readonly CanvasGroup visibility;

		private readonly MPEventSystem eventSystem;

		private GameObject savedSelection;

		private SelectableState[] selectables;

		private BehaviourState[] inputBehaviours;

		internal bool hidden { get; private set; }

		internal ChoicePanelState(PickupPickerPanel panel)
		{
			this.panel = panel;
			visibility = ((Component)panel).gameObject.AddComponent<CanvasGroup>();
			MPEventSystemLocator component = ((Component)panel).GetComponent<MPEventSystemLocator>();
			eventSystem = (((Object)(object)component != (Object)null) ? component.eventSystem : null);
		}

		internal void SetHidden(bool value)
		{
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)panel == (Object)null || (Object)(object)visibility == (Object)null)
			{
				return;
			}
			if (hidden == value)
			{
				if (hidden)
				{
					ClearPanelSelection();
				}
				return;
			}
			hidden = value;
			if (hidden)
			{
				savedSelection = (((Object)(object)eventSystem != (Object)null && IsPanelObject(((EventSystem)eventSystem).currentSelectedGameObject)) ? ((EventSystem)eventSystem).currentSelectedGameObject : null);
				ClearPanelSelection();
				Selectable[] componentsInChildren = ((Component)panel).GetComponentsInChildren<Selectable>(true);
				selectables = new SelectableState[componentsInChildren.Length];
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Selectable val = componentsInChildren[i];
					selectables[i] = new SelectableState
					{
						selectable = val,
						interactable = val.interactable,
						navigation = val.navigation
					};
					val.interactable = false;
					Navigation navigation = val.navigation;
					((Navigation)(ref navigation)).mode = (Mode)0;
					val.navigation = navigation;
				}
				List<Behaviour> list = new List<Behaviour>();
				list.AddRange((IEnumerable<Behaviour>)(object)((Component)panel).GetComponentsInChildren<GraphicRaycaster>(true));
				list.AddRange((IEnumerable<Behaviour>)(object)((Component)panel).GetComponentsInChildren<HGGamepadInputEvent>(true));
				list.AddRange((IEnumerable<Behaviour>)(object)((Component)panel).GetComponentsInChildren<UILayerKey>(true));
				inputBehaviours = new BehaviourState[list.Count];
				for (int j = 0; j < list.Count; j++)
				{
					inputBehaviours[j] = new BehaviourState
					{
						behaviour = list[j],
						enabled = list[j].enabled
					};
					list[j].enabled = false;
				}
				visibility.alpha = 0f;
				visibility.interactable = false;
				visibility.blocksRaycasts = false;
				return;
			}
			visibility.alpha = 1f;
			visibility.interactable = true;
			visibility.blocksRaycasts = true;
			SelectableState[] array = selectables;
			for (int k = 0; k < array.Length; k++)
			{
				SelectableState selectableState = array[k];
				if ((Object)(object)selectableState.selectable != (Object)null)
				{
					selectableState.selectable.interactable = selectableState.interactable;
					selectableState.selectable.navigation = selectableState.navigation;
				}
			}
			BehaviourState[] array2 = inputBehaviours;
			for (int k = 0; k < array2.Length; k++)
			{
				BehaviourState behaviourState = array2[k];
				if ((Object)(object)behaviourState.behaviour != (Object)null)
				{
					behaviourState.behaviour.enabled = behaviourState.enabled;
				}
			}
			if ((Object)(object)eventSystem != (Object)null && (Object)(object)savedSelection != (Object)null && savedSelection.activeInHierarchy)
			{
				Selectable component = savedSelection.GetComponent<Selectable>();
				if ((Object)(object)component != (Object)null && component.IsInteractable())
				{
					((EventSystem)eventSystem).SetSelectedGameObject(savedSelection);
				}
			}
			savedSelection = null;
			selectables = null;
			inputBehaviours = null;
		}

		private bool IsPanelObject(GameObject target)
		{
			if ((Object)(object)target != (Object)null)
			{
				if (!((Object)(object)target == (Object)(object)((Component)panel).gameObject))
				{
					return target.transform.IsChildOf(((Component)panel).transform);
				}
				return true;
			}
			return false;
		}

		private void ClearPanelSelection()
		{
			if ((Object)(object)eventSystem != (Object)null && IsPanelObject(((EventSystem)eventSystem).currentSelectedGameObject))
			{
				((EventSystem)eventSystem).SetSelectedGameObject((GameObject)null);
			}
		}
	}
	[BepInPlugin("com.local.threechoicechests", "ThreeChoiceChests", "1.0.2")]
	public class ThreeChoiceChestsPlugin : BaseUnityPlugin
	{
		private sealed class ActiveChoice
		{
			public PickupPickerController picker;

			public NetworkUIPromptController prompt;

			public PendingChoice pending;

			public CharacterMaster ownerMaster;

			public bool completed;

			public bool restoring;

			public ChoicePanelState panelState;
		}

		[HarmonyPatch(typeof(PickupPickerController), "OnDisplayBegin")]
		private static class BindChoicePanelPatch
		{
			private static void Postfix(PickupPickerController __instance, PickupPickerPanel ___panelInstanceController)
			{
				ActiveChoice currentChoice = ThreeChoiceChestsPlugin.currentChoice;
				if (OwnsPicker(currentChoice, __instance) && (Object)(object)___panelInstanceController != (Object)null)
				{
					currentChoice.panelState = new ChoicePanelState(___panelInstanceController);
					SyncChoicePanel(currentChoice);
				}
			}
		}

		[HarmonyPatch(typeof(PickupPickerPanel), "DestroyIt")]
		private static class PreserveChoicePanelPatch
		{
			private static bool Prefix(PickupPickerPanel __instance)
			{
				ActiveChoice currentChoice = ThreeChoiceChestsPlugin.currentChoice;
				if (!OwnsPicker(currentChoice, __instance.pickerController) || currentChoice.panelState == null || (Object)(object)currentChoice.panelState.panel != (Object)(object)__instance || !IsChoiceScoreboardOpen(currentChoice))
				{
					return true;
				}
				currentChoice.panelState.SetHidden(value: true);
				return false;
			}
		}

		[HarmonyPatch(typeof(HUD), "ActivateScoreboard")]
		private static class ScoreboardOpenedPatch
		{
			private static void Postfix(HUD __instance)
			{
				if ((Object)(object)GetChoiceHud(currentChoice) == (Object)(object)__instance)
				{
					SyncChoicePanel(currentChoice);
				}
			}
		}

		[HarmonyPatch(typeof(HUD), "DeactivateScoreboard")]
		private static class ScoreboardClosedPatch
		{
			private static void Postfix(HUD __instance)
			{
				if ((Object)(object)GetChoiceHud(currentChoice) == (Object)(object)__instance)
				{
					SyncChoicePanel(currentChoice);
				}
			}
		}

		[HarmonyPatch(typeof(PickupPickerController), "SubmitChoice")]
		private static class GuardHiddenChoiceInputPatch
		{
			private static bool Prefix(PickupPickerController __instance)
			{
				ActiveChoice currentChoice = ThreeChoiceChestsPlugin.currentChoice;
				if (OwnsPicker(currentChoice, __instance))
				{
					ChoicePanelState panelState = currentChoice.panelState;
					if (panelState == null || !panelState.hidden)
					{
						return !IsChoiceScoreboardOpen(currentChoice);
					}
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(PickupPickerController), "GetInspectInfoProvider")]
		private static class HideOwnedCommandInspectionPatch
		{
			private static void Postfix(PickupPickerController __instance, ref IInspectInfoProvider __result)
			{
				ActiveChoice currentChoice = ThreeChoiceChestsPlugin.currentChoice;
				if (OwnsPicker(currentChoice, __instance) && IsChoiceScoreboardOpen(currentChoice) && (Object)(object)currentChoice.prompt != (Object)null && (Object)(object)currentChoice.ownerMaster != (Object)null && (Object)(object)currentChoice.prompt.currentParticipantMaster == (Object)(object)currentChoice.ownerMaster)
				{
					__result = null;
				}
			}
		}

		[HarmonyPatch]
		private static class CreatePickupDropletPatch
		{
			private static MethodBase TargetMethod()
			{
				return typeof(PickupDropletController).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo method)
				{
					if (method.Name != "CreatePickupDroplet")
					{
						return false;
					}
					ParameterInfo[] parameters = method.GetParameters();
					return parameters.Length == 3 && parameters[0].ParameterType == typeof(CreatePickupInfo) && parameters[1].ParameterType == typeof(Vector3) && parameters[2].ParameterType == typeof(Vector3);
				});
			}

			private static bool Prefix(ref CreatePickupInfo __0, Vector3 __1, Vector3 __2)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return !TryCreateThreeChoicePicker(ref __0, __1);
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static hook_OnInteractionBegin <0>__PurchaseInteraction_OnInteractionBegin;

			public static Action<Run> <1>__ResetChoiceState;
		}

		public const string PluginGUID = "com.local.threechoicechests";

		public const string PluginName = "ThreeChoiceChests";

		public const string PluginVersion = "1.0.2";

		private Harmony harmony;

		private static GameObject commandCubePrefab;

		private static readonly Queue<PendingChoice> pendingChoices = new Queue<PendingChoice>();

		private static bool pickerActive;

		private static ActiveChoice currentChoice;

		private static ThreeChoiceChestsPlugin instance;

		private void Awake()
		{
			//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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			instance = this;
			MarkChest("RoR2/Base/Chest1/Chest1.prefab", ThreeChoiceChestCategory.General);
			MarkChest("RoR2/Base/CategoryChest/CategoryChestDamage.prefab", ThreeChoiceChestCategory.Damage);
			MarkChest("RoR2/Base/CategoryChest/CategoryChestHealing.prefab", ThreeChoiceChestCategory.Healing);
			MarkChest("RoR2/Base/CategoryChest/CategoryChestUtility.prefab", ThreeChoiceChestCategory.Utility);
			MarkChest("RoR2/DLC1/CategoryChest2/CategoryChest2Damage Variant.prefab", ThreeChoiceChestCategory.Damage);
			MarkChest("RoR2/DLC1/CategoryChest2/CategoryChest2Healing Variant.prefab", ThreeChoiceChestCategory.Healing);
			MarkChest("RoR2/DLC1/CategoryChest2/CategoryChest2Utility Variant.prefab", ThreeChoiceChestCategory.Utility);
			MarkChest("RoR2/Base/Chest2/Chest2.prefab", ThreeChoiceChestCategory.General);
			MarkChest("RoR2/Base/GoldChest/GoldChest.prefab", ThreeChoiceChestCategory.General);
			MarkChest("RoR2/Base/Chest1StealthedVariant/Chest1StealthedVariant.prefab", ThreeChoiceChestCategory.General);
			MarkChest("RoR2/Base/EquipmentBarrel/EquipmentBarrel.prefab", ThreeChoiceChestCategory.General);
			commandCubePrefab = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/Command/CommandCube.prefab").WaitForCompletion();
			if ((Object)(object)commandCubePrefab == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Could not load CommandCube prefab.");
				return;
			}
			object obj = <>O.<0>__PurchaseInteraction_OnInteractionBegin;
			if (obj == null)
			{
				hook_OnInteractionBegin val = PurchaseInteraction_OnInteractionBegin;
				<>O.<0>__PurchaseInteraction_OnInteractionBegin = val;
				obj = (object)val;
			}
			PurchaseInteraction.OnInteractionBegin += (hook_OnInteractionBegin)obj;
			harmony = new Harmony("com.local.threechoicechests");
			harmony.PatchAll(typeof(CreatePickupDropletPatch));
			harmony.PatchAll(typeof(PreserveChoicePanelPatch));
			harmony.PatchAll(typeof(BindChoicePanelPatch));
			harmony.PatchAll(typeof(ScoreboardOpenedPatch));
			harmony.PatchAll(typeof(ScoreboardClosedPatch));
			harmony.PatchAll(typeof(GuardHiddenChoiceInputPatch));
			harmony.PatchAll(typeof(HideOwnedCommandInspectionPatch));
			Run.onRunStartGlobal += ResetChoiceState;
			Run.onRunDestroyGlobal += ResetChoiceState;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"ThreeChoiceChests 1.0.2 loaded.");
		}

		private void OnDestroy()
		{
			//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_001b: Expected O, but got Unknown
			object obj = <>O.<0>__PurchaseInteraction_OnInteractionBegin;
			if (obj == null)
			{
				hook_OnInteractionBegin val = PurchaseInteraction_OnInteractionBegin;
				<>O.<0>__PurchaseInteraction_OnInteractionBegin = val;
				obj = (object)val;
			}
			PurchaseInteraction.OnInteractionBegin -= (hook_OnInteractionBegin)obj;
			Harmony obj2 = harmony;
			if (obj2 != null)
			{
				obj2.UnpatchSelf();
			}
			Run.onRunStartGlobal -= ResetChoiceState;
			Run.onRunDestroyGlobal -= ResetChoiceState;
			currentChoice?.panelState?.SetHidden(value: false);
			pendingChoices.Clear();
			pickerActive = false;
			currentChoice = null;
			instance = null;
		}

		private static void ResetChoiceState(Run run)
		{
			currentChoice?.panelState?.SetHidden(value: false);
			pendingChoices.Clear();
			pickerActive = false;
			currentChoice = null;
		}

		private void Update()
		{
			SyncChoicePanel(currentChoice);
		}

		private static bool OwnsPicker(ActiveChoice choice, PickupPickerController picker)
		{
			if (choice != null && !choice.completed && (Object)(object)choice.picker != (Object)null)
			{
				return (Object)(object)choice.picker == (Object)(object)picker;
			}
			return false;
		}

		private static HUD GetChoiceHud(ActiveChoice choice)
		{
			LocalUser obj = (((Object)(object)choice?.prompt != (Object)null) ? choice.prompt.currentLocalParticipant : null);
			CameraRigController val = ((obj != null) ? obj.cameraRigController : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return val.hud;
		}

		private static bool IsChoiceScoreboardOpen(ActiveChoice choice)
		{
			HUD choiceHud = GetChoiceHud(choice);
			if ((Object)(object)choiceHud != (Object)null && (Object)(object)choiceHud.scoreboardPanel != (Object)null)
			{
				return choiceHud.scoreboardPanel.activeInHierarchy;
			}
			return false;
		}

		private static void SyncChoicePanel(ActiveChoice choice)
		{
			if (choice != null && !choice.completed && choice == currentChoice)
			{
				choice.panelState?.SetHidden(IsChoiceScoreboardOpen(choice));
			}
		}

		private void MarkChest(string address, ThreeChoiceChestCategory category)
		{
			//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)
			GameObject val = Addressables.LoadAssetAsync<GameObject>((object)address).WaitForCompletion();
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Could not load chest prefab: " + address));
				return;
			}
			ThreeChoiceChestMarker threeChoiceChestMarker = val.GetComponent<ThreeChoiceChestMarker>();
			if ((Object)(object)threeChoiceChestMarker == (Object)null)
			{
				threeChoiceChestMarker = val.AddComponent<ThreeChoiceChestMarker>();
			}
			threeChoiceChestMarker.category = category;
		}

		private static void PurchaseInteraction_OnInteractionBegin(orig_OnInteractionBegin orig, PurchaseInteraction self, Interactor activator)
		{
			ThreeChoiceChestMarker component = ((Component)self).GetComponent<ThreeChoiceChestMarker>();
			if ((Object)(object)component != (Object)null && self.CanBeAffordedByInteractor(activator))
			{
				component.lastInteractor = activator;
			}
			orig.Invoke(self, activator);
		}

		private static bool TryCreateThreeChoicePicker(ref CreatePickupInfo pickupInfo, Vector3 position)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				return false;
			}
			ChestBehavior chest = pickupInfo.chest;
			if ((Object)(object)chest == (Object)null)
			{
				return false;
			}
			ThreeChoiceChestMarker component = ((Component)chest).GetComponent<ThreeChoiceChestMarker>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			if ((Object)(object)component.lastInteractor == (Object)null)
			{
				return false;
			}
			UniquePickup pickup = ((CreatePickupInfo)(ref pickupInfo)).pickup;
			if (!((UniquePickup)(ref pickup)).isValid)
			{
				return false;
			}
			Option[] array = BuildThreeOptions(pickup, component.category);
			if (array == null || array.Length == 0)
			{
				return false;
			}
			Interactor lastInteractor = component.lastInteractor;
			component.lastInteractor = null;
			pendingChoices.Enqueue(new PendingChoice
			{
				firstPickup = pickup,
				options = array,
				activator = lastInteractor,
				position = position,
				rotation = pickupInfo.rotation
			});
			if (!pickerActive)
			{
				OpenNextPendingChoice();
			}
			return true;
		}

		private static void OpenNextPendingChoice()
		{
			//IL_0046: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			if (!NetworkServer.active || pickerActive || pendingChoices.Count == 0)
			{
				return;
			}
			PendingChoice pendingChoice = pendingChoices.Dequeue();
			if ((Object)(object)pendingChoice.activator == (Object)null)
			{
				OpenNextPendingChoice();
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(commandCubePrefab, pendingChoice.position, pendingChoice.rotation);
			HideCommandCubePrefab(val);
			PickupPickerController component = val.GetComponent<PickupPickerController>();
			PickupIndexNetworker component2 = val.GetComponent<PickupIndexNetworker>();
			NetworkUIPromptController component3 = val.GetComponent<NetworkUIPromptController>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				OpenNextPendingChoice();
				return;
			}
			component2.NetworkpickupState = pendingChoice.firstPickup;
			pickerActive = true;
			NetworkServer.Spawn(val);
			CharacterBody component4 = ((Component)pendingChoice.activator).GetComponent<CharacterBody>();
			ActiveChoice choice = new ActiveChoice
			{
				picker = component,
				prompt = component3,
				pending = pendingChoice,
				ownerMaster = (((Object)(object)component4 != (Object)null) ? component4.master : null)
			};
			currentChoice = choice;
			if (component.onUniquePickupSelected == null)
			{
				component.onUniquePickupSelected = new UniquePickupUnityEvent();
			}
			((UnityEvent<UniquePickup>)(object)component.onUniquePickupSelected).AddListener((UnityAction<UniquePickup>)delegate
			{
				CompleteChoice(choice);
			});
			component3.onDisplayEnd += delegate
			{
				if (!choice.completed && !choice.restoring && (Object)(object)instance != (Object)null && NetworkServer.active)
				{
					choice.restoring = true;
					((MonoBehaviour)instance).StartCoroutine(RestoreChoiceAfterDisplayEnd(choice));
				}
			};
			component.SetOptionsServer(pendingChoice.options);
			if ((Object)(object)instance != (Object)null)
			{
				((MonoBehaviour)instance).StartCoroutine(OpenPickerAfterSpawn(component, pendingChoice.activator));
			}
		}

		private static void CompleteChoice(ActiveChoice choice)
		{
			if (!choice.completed && currentChoice == choice && NetworkServer.active)
			{
				choice.completed = true;
				if ((Object)(object)choice.prompt != (Object)null)
				{
					choice.prompt.SetParticipantMaster((CharacterMaster)null);
				}
				if ((Object)(object)choice.picker != (Object)null)
				{
					NetworkServer.Destroy(((Component)choice.picker).gameObject);
				}
				currentChoice = null;
				pickerActive = false;
				if ((Object)(object)instance != (Object)null)
				{
					((MonoBehaviour)instance).StartCoroutine(OpenNextChoiceNextFrame());
				}
			}
		}

		private static IEnumerator RestoreChoiceAfterDisplayEnd(ActiveChoice choice)
		{
			try
			{
				yield return (object)new WaitForSecondsRealtime(0.1f);
				while (!choice.completed && currentChoice == choice && (Object)(object)choice.picker != (Object)null && (Object)(object)choice.prompt != (Object)null && (Object)(object)choice.pending.activator != (Object)null && NetworkServer.active)
				{
					if (PauseManager.PauseScreenIsOpen() || IsChoiceScoreboardOpen(choice))
					{
						yield return null;
						continue;
					}
					if (!choice.prompt.isDisplaying)
					{
						choice.prompt.SetParticipantMasterFromInteractor(choice.pending.activator);
					}
					yield return (object)new WaitForSecondsRealtime(0.1f);
					if (!((Object)(object)choice.prompt != (Object)null) || !choice.prompt.isDisplaying)
					{
						continue;
					}
					break;
				}
			}
			finally
			{
				choice.restoring = false;
			}
		}

		private static IEnumerator OpenNextChoiceNextFrame()
		{
			yield return null;
			OpenNextPendingChoice();
		}

		private static IEnumerator OpenPickerAfterSpawn(PickupPickerController picker, Interactor activator)
		{
			yield return (object)new WaitForSecondsRealtime(0.1f);
			if (!((Object)(object)picker == (Object)null) && !((Object)(object)activator == (Object)null))
			{
				picker.OnInteractionBegin(activator);
			}
		}

		private static Option[] BuildThreeOptions(UniquePickup firstPickup, ThreeChoiceChestCategory category)
		{
			//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_0007: 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)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			PickupIndex pickupIndex = firstPickup.pickupIndex;
			PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex);
			if (pickupDef == null || (Object)(object)Run.instance == (Object)null)
			{
				return MakeOptions(new List<UniquePickup> { firstPickup });
			}
			List<PickupIndex> list = new List<PickupIndex>();
			if ((int)pickupDef.equipmentIndex != -1)
			{
				AddMatchingPickups(Run.instance.availableEquipmentDropList, pickupDef, category, equipmentMode: true, list);
			}
			else
			{
				AddMatchingPickups(Run.instance.availableTier1DropList, pickupDef, category, equipmentMode: false, list);
				AddMatchingPickups(Run.instance.availableTier2DropList, pickupDef, category, equipmentMode: false, list);
				AddMatchingPickups(Run.instance.availableTier3DropList, pickupDef, category, equipmentMode: false, list);
			}
			List<UniquePickup> list2 = new List<UniquePickup>();
			list2.Add(firstPickup);
			for (int num = list.Count - 1; num >= 0; num--)
			{
				if (list[num].value == pickupIndex.value)
				{
					list.RemoveAt(num);
				}
			}
			while (list2.Count < 3 && list.Count > 0)
			{
				int index = Random.Range(0, list.Count);
				PickupIndex val = list[index];
				list.RemoveAt(index);
				list2.Add(new UniquePickup(val));
			}
			return MakeOptions(list2);
		}

		private static void AddMatchingPickups(List<PickupIndex> source, PickupDef firstDef, ThreeChoiceChestCategory category, bool equipmentMode, List<PickupIndex> destination)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Invalid comparison between Unknown and I4
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			//IL_003a: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			if (source == null)
			{
				return;
			}
			foreach (PickupIndex item in source)
			{
				PickupDef pickupDef = PickupCatalog.GetPickupDef(item);
				if (pickupDef == null)
				{
					continue;
				}
				if (equipmentMode)
				{
					if ((int)pickupDef.equipmentIndex == -1)
					{
						continue;
					}
				}
				else if ((int)pickupDef.itemIndex == -1 || pickupDef.itemTier != firstDef.itemTier || !MatchesCategory(pickupDef, category))
				{
					continue;
				}
				bool flag = false;
				foreach (PickupIndex item2 in destination)
				{
					if (item2.value == item.value)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					destination.Add(item);
				}
			}
		}

		private static bool MatchesCategory(PickupDef pickupDef, ThreeChoiceChestCategory category)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (category == ThreeChoiceChestCategory.General)
			{
				return true;
			}
			if ((int)pickupDef.itemIndex == -1)
			{
				return false;
			}
			ItemDef itemDef = ItemCatalog.GetItemDef(pickupDef.itemIndex);
			if ((Object)(object)itemDef == (Object)null)
			{
				return false;
			}
			return category switch
			{
				ThreeChoiceChestCategory.Damage => itemDef.ContainsTag((ItemTag)1), 
				ThreeChoiceChestCategory.Healing => itemDef.ContainsTag((ItemTag)2), 
				ThreeChoiceChestCategory.Utility => itemDef.ContainsTag((ItemTag)3), 
				_ => true, 
			};
		}

		private static Option[] MakeOptions(List<UniquePickup> pickups)
		{
			//IL_0014: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			Option[] array = (Option[])(object)new Option[pickups.Count];
			for (int i = 0; i < pickups.Count; i++)
			{
				array[i] = new Option
				{
					pickup = pickups[i],
					available = true
				};
			}
			return array;
		}

		private static void HideCommandCubePrefab(GameObject prefab)
		{
			//IL_004e: 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)
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
			Light[] componentsInChildren2 = prefab.GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				((Behaviour)componentsInChildren2[i]).enabled = false;
			}
			ParticleSystem[] componentsInChildren3 = prefab.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem obj in componentsInChildren3)
			{
				EmissionModule emission = obj.emission;
				((EmissionModule)(ref emission)).enabled = false;
				obj.Stop(true, (ParticleSystemStopBehavior)0);
			}
			AudioSource[] componentsInChildren4 = prefab.GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource obj2 in componentsInChildren4)
			{
				obj2.playOnAwake = false;
				((Behaviour)obj2).enabled = false;
			}
		}
	}
	public class PendingChoice
	{
		public UniquePickup firstPickup;

		public Option[] options;

		public Interactor activator;

		public Vector3 position;

		public Quaternion rotation;
	}
	public enum ThreeChoiceChestCategory
	{
		General,
		Damage,
		Healing,
		Utility
	}
	public class ThreeChoiceChestMarker : MonoBehaviour
	{
		public ThreeChoiceChestCategory category;

		public Interactor lastInteractor;
	}
}