Decompiled source of ShareItemsWithMoreFun v0.2.2

ShareItemsWithMoreFun.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using EntityStates.CaptainSupplyDrop;
using EntityStates.HallowedCauldron;
using HG;
using On.EntityStates.CaptainSupplyDrop;
using On.EntityStates.HallowedCauldron;
using On.RoR2;
using On.RoR2.Quests.CompulsionQuests;
using On.RoR2.UI;
using R2API.Networking;
using R2API.Networking.Interfaces;
using R2API.Utils;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.Artifacts;
using RoR2.Orbs;
using RoR2.Quests;
using RoR2.Quests.CompulsionQuests;
using RoR2.UI;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceLocations;

[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("ShareItemsWithMoreFun")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.2.0")]
[assembly: AssemblyInformationalVersion("0.2.2+9cbb2eb87ee97e4840e21e4af04a3bf62c8825ba")]
[assembly: AssemblyProduct("ShareItemsWithMoreFun")]
[assembly: AssemblyTitle("ShareItemsWithMoreFun")]
[assembly: AssemblyVersion("0.2.2.0")]
namespace ShareItemsWithMoreFun;

internal static class BossRewards
{
	private const BindingFlags Private = BindingFlags.Instance | BindingFlags.NonPublic;

	private static readonly FieldInfo RngField = typeof(BossGroup).GetField("rng", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly FieldInfo BossDropsField = typeof(BossGroup).GetField("bossDrops", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly FieldInfo BossDropTablesField = typeof(BossGroup).GetField("bossDropTables", BindingFlags.Instance | BindingFlags.NonPublic);

	public static void Install()
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		if (RngField == null || BossDropsField == null || BossDropTablesField == null)
		{
			Plugin.Log.LogWarning((object)"Récompense du boss : champs de BossGroup introuvables, la récompense reste vanilla.");
		}
		else
		{
			BossGroup.DropRewards += new hook_DropRewards(BossGroup_DropRewards);
		}
	}

	private static void BossGroup_DropRewards(orig_DropRewards orig, BossGroup self)
	{
		Run instance = Run.instance;
		if (!NetworkServer.active || !Object.op_Implicit((Object)(object)instance) || !ModConfig.Enabled.Value || !ModConfig.InstancedBossRewards.Value || !self.scaleRewardsByPlayerCount || !Object.op_Implicit((Object)(object)self.dropPosition) || !IsTeleporterBoss(self))
		{
			orig.Invoke(self);
			return;
		}
		List<CharacterMaster> list = PlayerResolver.ShareOwners(ModConfig.ReviveDeadPlayersAfterTeleporter.Value);
		object? value = RngField.GetValue(self);
		Xoroshiro128Plus val = (Xoroshiro128Plus)((value is Xoroshiro128Plus) ? value : null);
		if (list.Count == 0 || val == null)
		{
			orig.Invoke(self);
			return;
		}
		int dropped = 0;
		try
		{
			DropPerPlayer(self, instance, list, val, ref dropped);
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"Récompense du boss : {arg}");
			if (dropped == 0)
			{
				orig.Invoke(self);
			}
		}
	}

	private static bool IsTeleporterBoss(BossGroup boss)
	{
		TeleporterInteraction instance = TeleporterInteraction.instance;
		if (!Object.op_Implicit((Object)(object)instance) || !((Object)(object)instance.bossGroup == (Object)(object)boss))
		{
			return Object.op_Implicit((Object)(object)((Component)boss).GetComponentInParent<TeleporterInteraction>());
		}
		return true;
	}

	private static void DropPerPlayer(BossGroup boss, Run run, List<CharacterMaster> players, Xoroshiro128Plus rng, ref int dropped)
	{
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: 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_00ae: Expected O, but got Unknown
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: 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_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		List<UniquePickup> list = BossDropsField.GetValue(boss) as List<UniquePickup>;
		List<PickupDropTable> list2 = BossDropTablesField.GetValue(boss) as List<PickupDropTable>;
		bool flag = list != null && list.Count > 0;
		bool flag2 = list2 != null && list2.Count > 0;
		UniquePickup val = default(UniquePickup);
		if (Object.op_Implicit((Object)(object)boss.dropTable))
		{
			val = boss.dropTable.GeneratePickup(rng);
		}
		else
		{
			List<PickupIndex> list3 = (boss.forceTier3Reward ? run.availableTier3DropList : run.availableTier2DropList);
			((UniquePickup)(ref val))..ctor(rng.NextElementUniform<PickupIndex>(list3));
		}
		int num = 1 + Math.Max(0, boss.bonusRewardCount);
		int num2 = num * players.Count;
		Xoroshiro128Plus rng2 = new Xoroshiro128Plus(rng.nextUlong);
		Vector3 val2 = Quaternion.AngleAxis((float)Random.Range(0, 360), Vector3.up) * (Vector3.up * 40f + Vector3.forward * 5f);
		Quaternion val3 = Quaternion.AngleAxis(360f / (float)num2, Vector3.up);
		Vector3 position = boss.dropPosition.position;
		foreach (CharacterMaster player in players)
		{
			using (DropContext.Begin(player, convertToChoices: true, rng2))
			{
				for (int i = 0; i < num; i++)
				{
					UniquePickup val4 = val;
					if ((flag || flag2) && rng.nextNormalizedFloat <= boss.bossDropChance)
					{
						if (flag2)
						{
							PickupDropTable val5 = rng.NextElementUniform<PickupDropTable>(list2);
							if (Object.op_Implicit((Object)(object)val5))
							{
								val4 = val5.GeneratePickup(rng);
							}
						}
						else
						{
							val4 = rng.NextElementUniform<UniquePickup>(list);
						}
					}
					PickupDropletController.CreatePickupDroplet(val4, position, val2, false);
					dropped++;
					val2 = val3 * val2;
				}
			}
		}
		Plugin.Debug($"Récompense du boss : {num} orbe(s) pour chacune des {players.Count} part(s), dont {players.FindAll((CharacterMaster p) => !Object.op_Implicit((Object)(object)p)).Count} libre(s)");
	}
}
internal static class ChestBalance
{
	private static readonly HashSet<string> BalanceableNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Chest1", "Chest2", "Chest1StealthedVariant", "CategoryChestDamage", "CategoryChestHealing", "CategoryChestUtility", "CategoryChest2Damage Variant", "CategoryChest2Healing Variant", "CategoryChest2Utility Variant", "EquipmentBarrel" };

	private static readonly List<GameObject> spawnedChests = new List<GameObject>();

	private static bool collecting;

	public static void Install()
	{
		SceneDirector.onPrePopulateSceneServer += delegate
		{
			spawnedChests.Clear();
			collecting = true;
		};
		SceneDirector.onSpawnInteractableServer += OnSpawnInteractable;
		SceneDirector.onPostPopulateSceneServer += OnPostPopulate;
	}

	private static void OnSpawnInteractable(SceneDirector director, GameObject spawned, DirectorCard card)
	{
		if (collecting && Object.op_Implicit((Object)(object)spawned) && IsBalanceable(((Object)spawned).name))
		{
			spawnedChests.Add(spawned);
		}
	}

	private static bool IsBalanceable(string objectName)
	{
		string text = ModConfig.NormalizeName(objectName);
		if (BalanceableNames.Contains(text))
		{
			return ModConfig.IsManagedChestName(text);
		}
		return false;
	}

	private static void OnPostPopulate(SceneDirector director)
	{
		collecting = false;
		try
		{
			RemoveSurplusChests();
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"Équilibrage des coffres : {arg}");
		}
		finally
		{
			spawnedChests.Clear();
		}
	}

	public static float KeepFraction(int players, float scaling, float baseCredits, float bonusCredits)
	{
		if (players <= 1 || scaling >= 1f)
		{
			return 1f;
		}
		if (baseCredits <= 0f)
		{
			baseCredits = 1f;
			bonusCredits = 0f;
		}
		float num = Mathf.Floor(baseCredits * (0.5f + 0.5f * (float)players)) + bonusCredits;
		float num2 = baseCredits * (1f + Mathf.Clamp01(scaling) * 0.5f * (float)(players - 1)) + bonusCredits;
		if (!(num > 0f))
		{
			return 1f;
		}
		return Mathf.Clamp01(num2 / num);
	}

	private static void RemoveSurplusChests()
	{
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Expected O, but got Unknown
		Run instance = Run.instance;
		if (!NetworkServer.active || !Object.op_Implicit((Object)(object)instance) || !ModConfig.Enabled.Value || !ModConfig.InstancedChests.Value || DelusionChestController.isDelusionEnable || instance is InfiniteTowerRun)
		{
			return;
		}
		if (InstanceTracker.GetInstancesList<CacheInteractables>().Count > 0)
		{
			Plugin.Debug("Équilibrage ignoré : scène d'épreuve");
			return;
		}
		int participatingPlayerCount = instance.participatingPlayerCount;
		StageCredits(out var baseCredits, out var bonusCredits);
		float num = KeepFraction(participatingPlayerCount, (float)ModConfig.MultiplayerChestScaling.Value / 100f, baseCredits, bonusCredits);
		if (num >= 1f)
		{
			return;
		}
		List<GameObject> list = spawnedChests.FindAll((GameObject chest) => Object.op_Implicit((Object)(object)chest));
		int num2 = list.Count - Mathf.RoundToInt((float)list.Count * num);
		if (num2 > 0)
		{
			Xoroshiro128Plus val = new Xoroshiro128Plus(instance.stageRng.nextUlong);
			for (int num3 = 0; num3 < num2; num3++)
			{
				int num4 = val.RangeInt(num3, list.Count);
				List<GameObject> list2 = list;
				int index = num3;
				int index2 = num4;
				GameObject value = list[num4];
				GameObject value2 = list[num3];
				list2[index] = value;
				list[index2] = value2;
				NetworkServer.Destroy(list[num3]);
			}
			Plugin.Debug($"Équilibrage : {num2} coffre(s) retiré(s) sur {list.Count} ({participatingPlayerCount} joueurs, réglage {ModConfig.MultiplayerChestScaling.Value} %)");
		}
	}

	private static void StageCredits(out float baseCredits, out float bonusCredits)
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: 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_0063: 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)
		baseCredits = 0f;
		bonusCredits = 0f;
		ClassicStageInfo val = (Object.op_Implicit((Object)(object)SceneInfo.instance) ? ((Component)SceneInfo.instance).GetComponent<ClassicStageInfo>() : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return;
		}
		baseCredits = val.sceneDirectorInteractibleCredits;
		if (val.bonusInteractibleCreditObjects == null)
		{
			return;
		}
		BonusInteractibleCreditObject[] bonusInteractibleCreditObjects = val.bonusInteractibleCreditObjects;
		foreach (BonusInteractibleCreditObject val2 in bonusInteractibleCreditObjects)
		{
			if (Object.op_Implicit((Object)(object)val2.objectThatGrantsPointsIfEnabled) && val2.objectThatGrantsPointsIfEnabled.activeSelf)
			{
				bonusCredits += val2.points;
			}
		}
	}
}
internal static class ChestHooks
{
	private const float DropDelaySeconds = 0.85f;

	public static void Install()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected O, but got Unknown
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Expected O, but got Unknown
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Expected O, but got Unknown
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Expected O, but got Unknown
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Expected O, but got Unknown
		ChestBehavior.Start += new hook_Start(ChestBehavior_Start);
		OptionChestBehavior.Start += new hook_Start(OptionChestBehavior_Start);
		PurchaseInteraction.OnInteractionBegin += new hook_OnInteractionBegin(PurchaseInteraction_OnInteractionBegin);
		PurchaseInteraction.SetAvailable += new hook_SetAvailable(PurchaseInteraction_SetAvailable);
		PurchaseInteraction.GetInteractability += new hook_GetInteractability(PurchaseInteraction_GetInteractability);
		PurchaseInteraction.onPurchaseGlobalServer += OnPurchaseGlobalServer;
		ChestBehavior.Open += new hook_Open(ChestBehavior_Open);
		ChestBehavior.OpenAndGrantViaOrb += new hook_OpenAndGrantViaOrb(ChestBehavior_OpenAndGrantViaOrb);
		ChestBehavior.ItemDrop += new hook_ItemDrop(ChestBehavior_ItemDrop);
		OptionChestBehavior.Open += new hook_Open(OptionChestBehavior_Open);
		OptionChestBehavior.ItemDrop += new hook_ItemDrop(OptionChestBehavior_ItemDrop);
	}

	private static void ChestBehavior_Start(orig_Start orig, ChestBehavior self)
	{
		orig.Invoke(self);
		if (CanManage(((Component)self).gameObject) && !self.isCommandChest)
		{
			bool instanced = HexHooks.IsConceptReliquary(((Component)self).gameObject) || ModConfig.InstancedChests.Value;
			ManagedChest managedChest = Setup(((Component)self).gameObject, instanced);
			if (Object.op_Implicit((Object)(object)managedChest))
			{
				managedChest.chest = self;
				managedChest.baseDropCount = Math.Max(1, self.dropCount);
				managedChest.neverConvert = HexHooks.IsConceptReliquary(((Component)self).gameObject);
			}
		}
	}

	private static void OptionChestBehavior_Start(orig_Start orig, OptionChestBehavior self)
	{
		orig.Invoke(self);
		if (ModConfig.InstancedChests.Value && CanManage(((Component)self).gameObject))
		{
			ManagedChest managedChest = Setup(((Component)self).gameObject, instanced: true);
			if (Object.op_Implicit((Object)(object)managedChest))
			{
				managedChest.optionChest = self;
			}
		}
	}

	private static bool CanManage(GameObject chestObject)
	{
		if (NetworkServer.active && ModConfig.Enabled.Value && !DelusionChestController.isDelusionEnable && Object.op_Implicit((Object)(object)Run.instance))
		{
			if (!ModConfig.IsManagedChestName(((Object)chestObject).name))
			{
				if (ModConfig.InstancedHexes.Value)
				{
					return HexHooks.IsConceptReliquary(chestObject);
				}
				return false;
			}
			return true;
		}
		return false;
	}

	internal static ManagedChest Setup(GameObject chestObject, bool instanced)
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Expected O, but got Unknown
		PurchaseInteraction component = chestObject.GetComponent<PurchaseInteraction>();
		if (!Object.op_Implicit((Object)(object)component))
		{
			return null;
		}
		ManagedChest orAdd = ManagedChest.GetOrAdd(chestObject);
		orAdd.serverManaged = true;
		orAdd.instanced = instanced;
		orAdd.remoteOpAllowed = instanced && ModConfig.RemoteOpCanOpenChests.Value;
		orAdd.purchase = component;
		orAdd.rng = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong);
		Plugin.Debug($"Coffre géré : {((Object)chestObject).name} (instancié : {instanced})");
		if (instanced)
		{
			ChestManagedMessage chestManagedMessage = ChestManagedMessage.For(orAdd);
			if (chestManagedMessage != null)
			{
				NetMessageExtensions.Send((INetMessage)(object)chestManagedMessage, (NetworkDestination)1);
			}
		}
		return orAdd;
	}

	private static bool TryGetServerInstanced(Component component, out ManagedChest managed)
	{
		managed = (NetworkServer.active ? component.GetComponent<ManagedChest>() : null);
		if (Object.op_Implicit((Object)(object)managed) && managed.serverManaged && managed.instanced)
		{
			return !managed.globallyOpened;
		}
		return false;
	}

	private static void PurchaseInteraction_OnInteractionBegin(orig_OnInteractionBegin orig, PurchaseInteraction self, Interactor activator)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		if (!TryGetServerInstanced((Component)(object)self, out var managed))
		{
			orig.Invoke(self, activator);
			return;
		}
		CharacterMaster val = PlayerResolver.FromInteractor(activator);
		if (!Object.op_Implicit((Object)(object)val) || managed.HasOpened(((NetworkBehaviour)val).netId))
		{
			return;
		}
		if (Object.op_Implicit((Object)(object)managed.shrine))
		{
			ShrineHooks.Purchase(managed, val, self, activator, orig);
			return;
		}
		if (Object.op_Implicit((Object)(object)managed.chest))
		{
			managed.chest.dropCount = managed.baseDropCount;
		}
		managed.purchaseInProgress = true;
		managed.purchaseSucceeded = false;
		managed.keepShopOpen = false;
		try
		{
			if (managed.isShopTerminal)
			{
				using (DropContext.Begin(val, convertToChoices: false, null))
				{
					orig.Invoke(self, activator);
				}
			}
			else
			{
				orig.Invoke(self, activator);
			}
		}
		finally
		{
			managed.purchaseInProgress = false;
		}
		if (!managed.purchaseSucceeded)
		{
			return;
		}
		if (managed.isShopTerminal)
		{
			OnShopTerminalPurchased(managed, val);
			return;
		}
		int num = ((!Object.op_Implicit((Object)(object)managed.chest)) ? 1 : Math.Max(1, managed.chest.dropCount));
		if (Object.op_Implicit((Object)(object)managed.chest))
		{
			managed.chest.dropCount = managed.baseDropCount;
		}
		managed.MarkOpened(((NetworkBehaviour)val).netId);
		ChestMarkers.MarkServer(managed);
		Plugin.Debug($"{((Object)val).name} a ouvert {((Object)self).name} ({num} drop(s))");
		NetMessageExtensions.Send((INetMessage)(object)new ChestOpenedMessage(((NetworkBehaviour)self).netId, ((NetworkBehaviour)val).netId, ChestVisual.PlayOpening), (NetworkDestination)1);
		((MonoBehaviour)managed).StartCoroutine(DropAfterDelay(managed, val, num));
	}

	private static void OnShopTerminalPurchased(ManagedChest boughtTerminal, CharacterMaster player)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		MultiShopController shop = boughtTerminal.shop;
		Plugin.Debug(((Object)player).name + " a acheté dans " + (Object.op_Implicit((Object)(object)shop) ? ((Object)shop).name : ((Object)boughtTerminal).name));
		ChestMarkers.MarkServer(boughtTerminal);
		if (!Object.op_Implicit((Object)(object)shop) || boughtTerminal.keepShopOpen)
		{
			boughtTerminal.MarkOpened(((NetworkBehaviour)player).netId);
			NetMessageExtensions.Send((INetMessage)(object)new ChestOpenedMessage(((NetworkBehaviour)boughtTerminal.purchase).netId, ((NetworkBehaviour)player).netId, ChestVisual.PlayOpening), (NetworkDestination)1);
			return;
		}
		Enumerator<GameObject> enumerator = shop.terminalGameObjectsList.GetEnumerator();
		try
		{
			while (enumerator.MoveNext())
			{
				GameObject current = enumerator.Current;
				ManagedChest managedChest = (Object.op_Implicit((Object)(object)current) ? current.GetComponent<ManagedChest>() : null);
				if (Object.op_Implicit((Object)(object)managedChest) && Object.op_Implicit((Object)(object)managedChest.purchase) && !managedChest.HasOpened(((NetworkBehaviour)player).netId))
				{
					managedChest.MarkOpened(((NetworkBehaviour)player).netId);
					NetMessageExtensions.Send((INetMessage)(object)new ChestOpenedMessage(((NetworkBehaviour)managedChest.purchase).netId, ((NetworkBehaviour)player).netId, ChestVisual.PlayOpening), (NetworkDestination)1);
				}
			}
		}
		finally
		{
			((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
		}
	}

	private static void OnPurchaseGlobalServer(PayCostContext context, PayCostResults results)
	{
		PurchaseInteraction val = context?.purchaseInteraction;
		ManagedChest managedChest = default(ManagedChest);
		if (Object.op_Implicit((Object)(object)val) && ((Component)val).TryGetComponent<ManagedChest>(ref managedChest) && managedChest.purchaseInProgress)
		{
			managedChest.purchaseSucceeded = true;
		}
	}

	private static IEnumerator DropAfterDelay(ManagedChest managed, CharacterMaster owner, int dropCount)
	{
		yield return (object)new WaitForSeconds(0.85f);
		if (!Object.op_Implicit((Object)(object)managed) || !NetworkServer.active)
		{
			yield break;
		}
		DropContext dropContext = null;
		UniquePickup currentPickup;
		try
		{
			if (Object.op_Implicit((Object)(object)managed.chest))
			{
				ChestBehavior chest = managed.chest;
				currentPickup = chest.currentPickup;
				if (!((UniquePickup)(ref currentPickup)).isValid)
				{
					chest.Roll();
				}
				chest.dropCount = dropCount;
				managed.allowItemDrop = true;
				using (dropContext = DropContext.Begin(owner, !managed.neverConvert, managed.rng))
				{
					chest.ItemDrop();
					yield break;
				}
			}
			if (Object.op_Implicit((Object)(object)managed.optionChest))
			{
				managed.optionChest.Roll();
				managed.allowItemDrop = true;
				using (dropContext = DropContext.Begin(owner, convertToChoices: false, managed.rng))
				{
					managed.optionChest.ItemDrop();
					yield break;
				}
			}
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"Échec du drop de {((Object)managed).name} : {arg}");
			int num = dropContext?.dropletsCreated ?? 0;
			DropPlainItemsAfterFailure(managed, owner, Object.op_Implicit((Object)(object)managed.chest) ? (dropCount - num) : (1 - num));
		}
		finally
		{
			managed.allowItemDrop = false;
			if (Object.op_Implicit((Object)(object)managed.chest))
			{
				managed.chest.dropCount = managed.baseDropCount;
				managed.chest.NetworkisChestOpened = false;
				currentPickup = managed.chest.currentPickup;
				if (!((UniquePickup)(ref currentPickup)).isValid)
				{
					managed.chest.Roll();
				}
			}
		}
	}

	private static void DropPlainItemsAfterFailure(ManagedChest managed, CharacterMaster owner, int missing)
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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)
		//IL_00a9: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		if (missing <= 0)
		{
			return;
		}
		try
		{
			if (Object.op_Implicit((Object)(object)managed.optionChest))
			{
				managed.allowItemDrop = true;
				using (DropContext.Begin(owner, convertToChoices: false, null))
				{
					managed.optionChest.ItemDrop();
					return;
				}
			}
			ChestBehavior chest = managed.chest;
			if (!Object.op_Implicit((Object)(object)chest) || !Object.op_Implicit((Object)(object)chest.dropTransform))
			{
				return;
			}
			Vector3 val = chest.dropTransform.position + Vector3.up * 1.5f;
			Vector3 val2 = Vector3.up * chest.dropUpVelocityStrength + chest.dropTransform.forward * chest.dropForwardVelocityStrength;
			Quaternion val3 = Quaternion.AngleAxis(360f / (float)missing, Vector3.up);
			using (DropContext.Begin(owner, convertToChoices: false, null))
			{
				for (int i = 0; i < missing; i++)
				{
					UniquePickup currentPickup = chest.currentPickup;
					if (!((UniquePickup)(ref currentPickup)).isValid)
					{
						chest.Roll();
					}
					currentPickup = chest.currentPickup;
					if (!((UniquePickup)(ref currentPickup)).isValid)
					{
						break;
					}
					PickupDropletController.CreatePickupDroplet(chest.currentPickup, val, val2, false);
					val2 = val3 * val2;
					chest.Roll();
				}
			}
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"Le drop de secours a aussi échoué : {arg}");
		}
	}

	private static void PurchaseInteraction_SetAvailable(orig_SetAvailable orig, PurchaseInteraction self, bool newAvailable)
	{
		if (newAvailable || !TryGetServerInstanced((Component)(object)self, out var managed) || !managed.purchaseInProgress)
		{
			orig.Invoke(self, newAvailable);
		}
	}

	private static void ChestBehavior_Open(orig_Open orig, ChestBehavior self)
	{
		if (TryGetServerInstanced((Component)(object)self, out var managed))
		{
			if (managed.purchaseInProgress)
			{
				return;
			}
			managed.globallyOpened = true;
			Plugin.Debug(((Object)self).name + " ouvert hors achat : retour au comportement vanilla");
		}
		orig.Invoke(self);
	}

	private static void ChestBehavior_OpenAndGrantViaOrb(orig_OpenAndGrantViaOrb orig, ChestBehavior self, Interactor interactor)
	{
		if (TryGetServerInstanced((Component)(object)self, out var managed))
		{
			if (managed.purchaseInProgress)
			{
				return;
			}
			managed.globallyOpened = true;
		}
		orig.Invoke(self, interactor);
	}

	private static void OptionChestBehavior_Open(orig_Open orig, OptionChestBehavior self)
	{
		if (TryGetServerInstanced((Component)(object)self, out var managed))
		{
			if (managed.purchaseInProgress)
			{
				return;
			}
			managed.globallyOpened = true;
		}
		orig.Invoke(self);
	}

	private static void ChestBehavior_ItemDrop(orig_ItemDrop orig, ChestBehavior self)
	{
		ManagedChest managedChest = (NetworkServer.active ? ((Component)self).GetComponent<ManagedChest>() : null);
		if (!Object.op_Implicit((Object)(object)managedChest) || !managedChest.serverManaged || managedChest.globallyOpened)
		{
			orig.Invoke(self);
			return;
		}
		if (managedChest.instanced)
		{
			if (managedChest.allowItemDrop)
			{
				managedChest.allowItemDrop = false;
				orig.Invoke(self);
			}
			return;
		}
		using (DropContext.Begin(PlayerResolver.FromInteractor(Object.op_Implicit((Object)(object)managedChest.purchase) ? managedChest.purchase.lastActivator : null), convertToChoices: true, managedChest.rng))
		{
			orig.Invoke(self);
		}
	}

	private static void OptionChestBehavior_ItemDrop(orig_ItemDrop orig, OptionChestBehavior self)
	{
		ManagedChest managedChest = (NetworkServer.active ? ((Component)self).GetComponent<ManagedChest>() : null);
		if (Object.op_Implicit((Object)(object)managedChest) && managedChest.serverManaged && managedChest.instanced && !managedChest.globallyOpened)
		{
			if (managedChest.allowItemDrop)
			{
				managedChest.allowItemDrop = false;
				orig.Invoke(self);
			}
		}
		else
		{
			orig.Invoke(self);
		}
	}

	private static Interactability PurchaseInteraction_GetInteractability(orig_GetInteractability orig, PurchaseInteraction self, Interactor activator)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: 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)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		Interactability val = orig.Invoke(self, activator);
		ManagedChest component = ((Component)self).GetComponent<ManagedChest>();
		if ((int)val == 0 && RemoteOperation.CanOpenChest(self, component, activator))
		{
			val = RemoteOperation.EvaluateAsAllowed(self, activator, orig);
		}
		if ((int)val == 0)
		{
			return val;
		}
		bool alreadyOpened = default(bool);
		if (Object.op_Implicit((Object)(object)component) && component.IsInstancedFor(activator, out alreadyOpened) && alreadyOpened)
		{
			return (Interactability)0;
		}
		if (Object.op_Implicit((Object)(object)component) && component.IsShrineCoolingDown(PlayerResolver.FromInteractor(activator)))
		{
			return (Interactability)0;
		}
		return val;
	}
}
internal static class ChestMarkers
{
	private sealed class Marker
	{
		public ManagedChest chest;

		public PingIndicator indicator;
	}

	private const float RefreshSeconds = 0.25f;

	private const BindingFlags Private = BindingFlags.Instance | BindingFlags.NonPublic;

	private static readonly FieldInfo FixedTimerField = typeof(PingIndicator).GetField("fixedTimer", BindingFlags.Instance | BindingFlags.NonPublic);

	private static readonly List<Marker> markers = new List<Marker>();

	private static GameObject prefab;

	private static bool buildingMarker;

	private static float nextRefresh;

	public static void Install()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Expected O, but got Unknown
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Expected O, but got Unknown
		if (FixedTimerField == null)
		{
			Plugin.Log.LogWarning((object)"Coffres marqués : minuteur du ping introuvable, le marqueur sera recréé à chaque fin de ping.");
		}
		PingerController.CmdPing += new hook_CmdPing(PingerController_CmdPing);
		Chat.AddMessage_string += new hook_AddMessage_string(Chat_AddMessage_string);
	}

	public static void MarkServer(ManagedChest managed)
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		if (NetworkServer.active && ModConfig.Enabled.Value && ModConfig.PersistentChestMarkers.Value && Object.op_Implicit((Object)(object)managed) && !managed.marked && managed.serverManaged && managed.instanced && !managed.globallyOpened && !Object.op_Implicit((Object)(object)managed.shrine) && Object.op_Implicit((Object)(object)managed.purchase))
		{
			managed.marked = true;
			Plugin.Debug("Coffre marqué : " + ((Object)managed).name);
			NetMessageExtensions.Send((INetMessage)(object)new ChestMarkedMessage(((NetworkBehaviour)managed.purchase).netId), (NetworkDestination)1);
		}
	}

	private static void PingerController_CmdPing(orig_CmdPing orig, PingerController self, PingInfo incomingPing)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		orig.Invoke(self, incomingPing);
		if (NetworkServer.active && incomingPing.active)
		{
			GameObject targetGameObject = ((PingInfo)(ref incomingPing)).targetGameObject;
			ManagedChest managedChest = (Object.op_Implicit((Object)(object)targetGameObject) ? targetGameObject.GetComponent<ManagedChest>() : null);
			if (Object.op_Implicit((Object)(object)managedChest))
			{
				MarkServer(managedChest);
			}
		}
	}

	public static void Tick()
	{
		if (Time.unscaledTime < nextRefresh)
		{
			return;
		}
		nextRefresh = Time.unscaledTime + 0.25f;
		for (int num = markers.Count - 1; num >= 0; num--)
		{
			Marker marker = markers[num];
			if (!Object.op_Implicit((Object)(object)marker.chest) || !Object.op_Implicit((Object)(object)marker.indicator) || !ShouldShow(marker.chest))
			{
				if (Object.op_Implicit((Object)(object)marker.indicator))
				{
					Object.Destroy((Object)(object)((Component)marker.indicator).gameObject);
				}
				markers.RemoveAt(num);
			}
		}
		foreach (ManagedChest instance in ManagedChest.Instances)
		{
			if (Object.op_Implicit((Object)(object)instance) && instance.marked && !HasMarker(instance) && ShouldShow(instance))
			{
				Create(instance);
			}
		}
	}

	private static bool ShouldShow(ManagedChest managed)
	{
		if (!managed.marked || !managed.instanced || managed.globallyOpened || Object.op_Implicit((Object)(object)managed.shrine))
		{
			return false;
		}
		PurchaseInteraction component = ((Component)managed).GetComponent<PurchaseInteraction>();
		if (!Object.op_Implicit((Object)(object)component) || !component.available)
		{
			return false;
		}
		if (IsCarried(((Component)managed).gameObject))
		{
			return false;
		}
		MultiShopController componentInParent = ((Component)managed).GetComponentInParent<MultiShopController>();
		if (Object.op_Implicit((Object)(object)componentInParent) && IsCarried(((Component)componentInParent).gameObject))
		{
			return false;
		}
		if (LocalUserManager.readOnlyLocalUsersList.Count > 0)
		{
			return !managed.OpenedByAllLocalPlayers();
		}
		return false;
	}

	private static bool IsCarried(GameObject gameObject)
	{
		return Object.op_Implicit((Object)(object)VehicleSeat.FindVehicleSeatWithPassenger(gameObject, (VehicleSeat)null));
	}

	private static bool HasMarker(ManagedChest managed)
	{
		foreach (Marker marker in markers)
		{
			if ((Object)(object)marker.chest == (Object)(object)managed)
			{
				return true;
			}
		}
		return false;
	}

	private static void Create(ManagedChest managed)
	{
		//IL_0057: 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)
		if (!Object.op_Implicit((Object)(object)prefab))
		{
			prefab = LegacyResourcesAPI.Load<GameObject>("Prefabs/PingIndicator");
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return;
			}
		}
		GameObject val = Object.Instantiate<GameObject>(prefab);
		PingIndicator component = val.GetComponent<PingIndicator>();
		if (!Object.op_Implicit((Object)(object)component))
		{
			Object.Destroy((Object)(object)val);
			return;
		}
		component.pingOwner = null;
		component.pingOrigin = ((Component)managed).transform.position;
		component.pingNormal = Vector3.up;
		component.pingTarget = ((Component)managed).gameObject;
		buildingMarker = true;
		try
		{
			component.RebuildPing();
		}
		finally
		{
			buildingMarker = false;
		}
		if (Object.op_Implicit((Object)(object)component.pingText))
		{
			((Behaviour)component.pingText).enabled = false;
		}
		FixedTimerField?.SetValue(component, float.PositiveInfinity);
		markers.Add(new Marker
		{
			chest = managed,
			indicator = component
		});
	}

	private static void Chat_AddMessage_string(orig_AddMessage_string orig, string message)
	{
		if (!buildingMarker)
		{
			orig.Invoke(message);
		}
	}
}
internal static class ChoiceBuilder
{
	private static readonly ItemTag[] SpecialTags;

	public static bool TryConvert(ref CreatePickupInfo info, Xoroshiro128Plus rng)
	{
		//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_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Expected O, but got Unknown
		//IL_006c: 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_00b6: 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_00f1: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		UniquePickup pickup = ((CreatePickupInfo)(ref info)).pickup;
		PickupDef def = (((UniquePickup)(ref pickup)).isValid ? PickupCatalog.GetPickupDef(pickup.pickupIndex) : null);
		string text = QualityKey(def);
		if (text == null || !Object.op_Implicit((Object)(object)Run.instance))
		{
			return false;
		}
		if (rng == null)
		{
			rng = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong);
		}
		PickupDropTable table = (Object.op_Implicit((Object)(object)info.chest) ? info.chest.dropTable : null);
		List<PickupIndex> list = CollectCandidates(pickup, text, table, onlyTableLists: true);
		if (list.Count == 0)
		{
			list = CollectCandidates(pickup, text, table, onlyTableLists: false);
		}
		int num = Math.Min(ModConfig.ChoiceCount.Value - 1, list.Count);
		if (num < 1)
		{
			return false;
		}
		List<UniquePickup> list2 = new List<UniquePickup>(num + 1) { pickup };
		for (int i = 0; i < num; i++)
		{
			int num2 = rng.RangeInt(i, list.Count);
			List<PickupIndex> list3 = list;
			int index = i;
			List<PickupIndex> list4 = list;
			int index2 = num2;
			PickupIndex value = list[num2];
			PickupIndex value2 = list[i];
			list3[index] = value;
			list4[index2] = value2;
			list2.Add(((UniquePickup)(ref pickup)).WithPickupIndex(list[i]));
		}
		for (int num3 = list2.Count - 1; num3 > 0; num3--)
		{
			int num4 = rng.RangeInt(0, num3 + 1);
			List<UniquePickup> list5 = list2;
			int index2 = num3;
			int index = num4;
			UniquePickup value3 = list2[num4];
			UniquePickup value4 = list2[num3];
			list5[index2] = value3;
			list2[index] = value4;
		}
		GameObject val = OptionPickupPrefab.Get();
		if (!Object.op_Implicit((Object)(object)val))
		{
			return false;
		}
		info.pickerOptions = PickupPickerController.GenerateOptionsFromList<List<UniquePickup>>(list2);
		info.maxOptionCount = 1;
		info.prefabOverride = val;
		((CreatePickupInfo)(ref info)).pickup = DisplayPickup(pickup, def);
		Plugin.Debug($"Orbe : {list2.Count} choix de qualité {text}");
		return true;
	}

	private static string QualityKey(PickupDef def)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Invalid comparison between Unknown and I4
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Invalid comparison between Unknown and I4
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: 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_002a: Invalid comparison between Unknown and I4
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Invalid comparison between Unknown and I4
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Expected I4, but got Unknown
		if (def == null)
		{
			return null;
		}
		if ((int)def.itemIndex != -1)
		{
			ItemDef itemDef = ItemCatalog.GetItemDef(def.itemIndex);
			if (!Object.op_Implicit((Object)(object)itemDef) || (int)itemDef.tier == 13)
			{
				return null;
			}
			if ((int)itemDef.tier != 3)
			{
				return "item:" + (int)itemDef.tier;
			}
			return "lunar";
		}
		if ((int)def.equipmentIndex != -1)
		{
			EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(def.equipmentIndex);
			if (!Object.op_Implicit((Object)(object)equipmentDef))
			{
				return null;
			}
			if (equipmentDef.isLunar)
			{
				return "lunar";
			}
			if (!equipmentDef.isBoss)
			{
				return "equipment";
			}
			return "equipment:boss";
		}
		return null;
	}

	private static List<PickupIndex> CollectCandidates(UniquePickup rolled, string quality, PickupDropTable table, bool onlyTableLists)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		List<PickupIndex> list = new List<PickupIndex>();
		HashSet<PickupIndex> hashSet = new HashSet<PickupIndex> { rolled.pickupIndex };
		BasicPickupDropTable val = (BasicPickupDropTable)(object)((table is BasicPickupDropTable) ? table : null);
		bool flag = Object.op_Implicit((Object)(object)val) && val.IsFilterRequired();
		foreach (var (list2, num) in DropLists(Run.instance, val))
		{
			if (list2 == null || (onlyTableLists && Object.op_Implicit((Object)(object)val) && num <= 0f))
			{
				continue;
			}
			foreach (PickupIndex item in list2)
			{
				if (hashSet.Add(item))
				{
					PickupDef pickupDef = PickupCatalog.GetPickupDef(item);
					if (!(QualityKey(pickupDef) != quality) && (!flag || val.PassesFilter(item)) && AllowsStorageFlags(pickupDef, rolled) && SameSpecialTags(pickupDef, rolled))
					{
						list.Add(item);
					}
				}
			}
		}
		return list;
	}

	private static IEnumerable<(List<PickupIndex>, float)> DropLists(Run run, BasicPickupDropTable t)
	{
		bool b = Object.op_Implicit((Object)(object)t);
		yield return (run.availableTier1DropList, b ? t.tier1Weight : 1f);
		yield return (run.availableTier2DropList, b ? t.tier2Weight : 1f);
		yield return (run.availableTier3DropList, b ? t.tier3Weight : 1f);
		yield return (run.availableBossDropList, b ? t.bossWeight : 1f);
		yield return (run.availableLunarItemDropList, b ? t.lunarItemWeight : 1f);
		yield return (run.availableLunarEquipmentDropList, b ? t.lunarEquipmentWeight : 1f);
		yield return (run.availableLunarCombinedDropList, b ? t.lunarCombinedWeight : 1f);
		yield return (run.availableEquipmentDropList, b ? t.equipmentWeight : 1f);
		yield return (run.availableVoidTier1DropList, b ? t.voidTier1Weight : 1f);
		yield return (run.availableVoidTier2DropList, b ? t.voidTier2Weight : 1f);
		yield return (run.availableVoidTier3DropList, b ? t.voidTier3Weight : 1f);
		yield return (run.availableVoidBossDropList, b ? t.voidBossWeight : 1f);
		yield return (run.availableFoodTierDropList, b ? t.foodTierWeight : 1f);
		yield return (run.availablePowerShapeItemsDropList, b ? t.powerShapesWeight : 1f);
		yield return (run.availableCursedTierDropList, b ? t.cursedWeight : 1f);
		yield return (run.availableHexTierDropList, b ? t.hexWeight : 1f);
		yield return (run.availablePageTierDropList, b ? t.pageWeight : 1f);
	}

	private static bool SameSpecialTags(PickupDef candidate, UniquePickup rolled)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Invalid comparison between Unknown and I4
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		if ((int)candidate.itemIndex == -1)
		{
			return true;
		}
		PickupDef pickupDef = PickupCatalog.GetPickupDef(rolled.pickupIndex);
		ItemDef itemDef = ItemCatalog.GetItemDef(candidate.itemIndex);
		ItemDef val = ((pickupDef != null && (int)pickupDef.itemIndex != -1) ? ItemCatalog.GetItemDef(pickupDef.itemIndex) : null);
		ItemTag[] specialTags = SpecialTags;
		foreach (ItemTag val2 in specialTags)
		{
			bool num = Object.op_Implicit((Object)(object)itemDef) && itemDef.ContainsTag(val2);
			bool flag = Object.op_Implicit((Object)(object)val) && val.ContainsTag(val2);
			if (num != flag)
			{
				return false;
			}
		}
		return true;
	}

	private static bool AllowsStorageFlags(PickupDef def, UniquePickup rolled)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_001f: 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_0012: Unknown result type (might be due to invalid IL or missing references)
		if ((int)def.itemIndex == -1)
		{
			if (!((UniquePickup)(ref rolled)).isTempItem)
			{
				return !rolled.isRental;
			}
			return false;
		}
		ItemDef itemDef = ItemCatalog.GetItemDef(def.itemIndex);
		if (((UniquePickup)(ref rolled)).isTempItem && !itemDef.ContainsTag((ItemTag)31))
		{
			return false;
		}
		if (rolled.isRental && !itemDef.ContainsTag((ItemTag)40))
		{
			return false;
		}
		return true;
	}

	private static UniquePickup DisplayPickup(UniquePickup rolled, PickupDef def)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Invalid comparison between Unknown and I4
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: 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_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0038: 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_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		ItemTier val;
		if ((int)def.itemIndex != -1)
		{
			val = ItemCatalog.GetItemDef(def.itemIndex).tier;
		}
		else
		{
			if ((int)def.equipmentIndex == -1 || !EquipmentCatalog.GetEquipmentDef(def.equipmentIndex).isLunar)
			{
				return rolled;
			}
			val = (ItemTier)3;
		}
		PickupIndex val2 = PickupCatalog.FindPickupIndex(val);
		if (!((PickupIndex)(ref val2)).isValid)
		{
			return rolled;
		}
		return ((UniquePickup)(ref rolled)).WithPickupIndex(val2);
	}

	static ChoiceBuilder()
	{
		ItemTag[] array = new ItemTag[3];
		RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
		SpecialTags = (ItemTag[])(object)array;
	}
}
internal static class ClientHooks
{
	public static void Install()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected O, but got Unknown
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		PurchaseInteraction.ShouldDisplayHologram += new hook_ShouldDisplayHologram(PurchaseInteraction_ShouldDisplayHologram);
		PurchaseInteraction.ShouldShowOnScanner += new hook_ShouldShowOnScanner(PurchaseInteraction_ShouldShowOnScanner);
		PurchaseInteraction.ShouldProximityHighlight += new hook_ShouldProximityHighlight(PurchaseInteraction_ShouldProximityHighlight);
		PickupPickerController.ShouldShowOnScanner += new hook_ShouldShowOnScanner(PickupPickerController_ShouldShowOnScanner);
		GenericPickupController.ShouldShowOnScanner += new hook_ShouldShowOnScanner(GenericPickupController_ShouldShowOnScanner);
		MultiShopController.ShouldDisplayHologram += new hook_ShouldDisplayHologram(MultiShopController_ShouldDisplayHologram);
	}

	private static bool MultiShopController_ShouldDisplayHologram(orig_ShouldDisplayHologram orig, MultiShopController self, GameObject viewer)
	{
		//IL_002c: 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)
		if (!orig.Invoke(self, viewer))
		{
			return false;
		}
		CharacterMaster val = (Object.op_Implicit((Object)(object)viewer) ? PlayerResolver.FromBody(viewer.GetComponent<CharacterBody>()) : null);
		if (Object.op_Implicit((Object)(object)val) && PlayerResolver.IsLocalPlayer(((NetworkBehaviour)val).netId))
		{
			return !MultiShopHooks.ClosedFor(self, ((NetworkBehaviour)val).netId);
		}
		return !MultiShopHooks.ClosedForAllLocalPlayers(self);
	}

	private static bool PurchaseInteraction_ShouldDisplayHologram(orig_ShouldDisplayHologram orig, PurchaseInteraction self, GameObject viewer)
	{
		if (orig.Invoke(self, viewer) && !OpenedForLocalView(self, viewer))
		{
			return !ShrineCoolingDownForLocalView(self, viewer);
		}
		return false;
	}

	private static bool ShrineCoolingDownForLocalView(PurchaseInteraction purchase, GameObject viewer)
	{
		ManagedChest component = ((Component)purchase).GetComponent<ManagedChest>();
		if (Object.op_Implicit((Object)(object)component))
		{
			return component.IsShrineCoolingDown(ShrineHooks.LocalViewer(Object.op_Implicit((Object)(object)viewer) ? viewer.transform : null));
		}
		return false;
	}

	private static bool PurchaseInteraction_ShouldShowOnScanner(orig_ShouldShowOnScanner orig, PurchaseInteraction self)
	{
		if (orig.Invoke(self))
		{
			return !OpenedForLocalView(self, null);
		}
		return false;
	}

	private static bool PurchaseInteraction_ShouldProximityHighlight(orig_ShouldProximityHighlight orig, PurchaseInteraction self)
	{
		if (orig.Invoke(self))
		{
			return !OpenedForLocalView(self, null);
		}
		return false;
	}

	private static bool PickupPickerController_ShouldShowOnScanner(orig_ShouldShowOnScanner orig, PickupPickerController self)
	{
		if (orig.Invoke(self))
		{
			return !HiddenLocally((Component)(object)self);
		}
		return false;
	}

	private static bool GenericPickupController_ShouldShowOnScanner(orig_ShouldShowOnScanner orig, GenericPickupController self)
	{
		if (orig.Invoke(self))
		{
			return !HiddenLocally((Component)(object)self);
		}
		return false;
	}

	private static bool HiddenLocally(Component component)
	{
		OwnedObject component2 = component.GetComponent<OwnedObject>();
		if (Object.op_Implicit((Object)(object)component2))
		{
			return component2.ShouldHideLocally();
		}
		return false;
	}

	private static bool OpenedForLocalView(PurchaseInteraction purchase, GameObject viewer)
	{
		//IL_0031: 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)
		ManagedChest component = ((Component)purchase).GetComponent<ManagedChest>();
		if (!Object.op_Implicit((Object)(object)component))
		{
			return false;
		}
		CharacterMaster val = (Object.op_Implicit((Object)(object)viewer) ? PlayerResolver.FromBody(viewer.GetComponent<CharacterBody>()) : null);
		if (Object.op_Implicit((Object)(object)val) && PlayerResolver.IsLocalPlayer(((NetworkBehaviour)val).netId))
		{
			if (component.instanced && !component.globallyOpened)
			{
				return component.HasOpened(((NetworkBehaviour)val).netId);
			}
			return false;
		}
		return component.OpenedByAnyLocalPlayer();
	}
}
internal static class ClientVisuals
{
	private sealed class AnimatorBridge : EntityState
	{
		public static bool Play(Animator animator, string layer, string state, string playbackRateParam, float duration)
		{
			if (!HasState(animator, layer, state))
			{
				return false;
			}
			EntityState.PlayAnimationOnAnimator(animator, layer, state, playbackRateParam, duration, 0f);
			return true;
		}

		public static bool Play(Animator animator, string layer, string state)
		{
			if (!HasState(animator, layer, state))
			{
				return false;
			}
			EntityState.PlayAnimationOnAnimator(animator, layer, state);
			return true;
		}

		private static bool HasState(Animator animator, string layer, string state)
		{
			int layerIndex = animator.GetLayerIndex(layer);
			if (layerIndex >= 0)
			{
				return animator.HasState(layerIndex, Animator.StringToHash(state));
			}
			return false;
		}
	}

	private const float OpeningSeconds = 1f;

	public static void PlayLocalOpening(GameObject chestObject)
	{
		ManagedChest component = chestObject.GetComponent<ManagedChest>();
		if (Object.op_Implicit((Object)(object)component))
		{
			component.localOpenedShown = true;
		}
		if (TryShowShrineDone(chestObject, component))
		{
			return;
		}
		ShopTerminalBehavior component2 = chestObject.GetComponent<ShopTerminalBehavior>();
		if (Object.op_Implicit((Object)(object)component2))
		{
			if (!Object.op_Implicit((Object)(object)component) || component.OpenedByAllLocalPlayers())
			{
				CloseShopTerminal(component2, playSound: true);
			}
			return;
		}
		Animator val = FindAnimator(chestObject);
		if (Object.op_Implicit((Object)(object)val) && AnimatorBridge.Play(val, "Body", "Opening", "Opening.playbackRate", 1f) && Object.op_Implicit((Object)(object)component))
		{
			((MonoBehaviour)component).StartCoroutine(FinishOpening(val));
		}
		HideReliquaryGlow(chestObject, component);
		SfxLocator component3 = chestObject.GetComponent<SfxLocator>();
		if (Object.op_Implicit((Object)(object)component3) && !string.IsNullOrEmpty(component3.openSound))
		{
			Util.PlaySound(component3.openSound, chestObject);
		}
	}

	public static void ShowOpened(GameObject chestObject)
	{
		ManagedChest component = chestObject.GetComponent<ManagedChest>();
		if (Object.op_Implicit((Object)(object)component))
		{
			component.localOpenedShown = true;
		}
		if (TryShowShrineDone(chestObject, component))
		{
			return;
		}
		ShopTerminalBehavior component2 = chestObject.GetComponent<ShopTerminalBehavior>();
		if (Object.op_Implicit((Object)(object)component2))
		{
			if (!Object.op_Implicit((Object)(object)component) || component.OpenedByAllLocalPlayers())
			{
				CloseShopTerminal(component2, playSound: false);
			}
			return;
		}
		Animator val = FindAnimator(chestObject);
		if (Object.op_Implicit((Object)(object)val))
		{
			AnimatorBridge.Play(val, "Body", "Opened");
		}
		HideReliquaryGlow(chestObject, component);
	}

	private static void HideReliquaryGlow(GameObject chestObject, ManagedChest managed)
	{
		if (!HexHooks.IsConceptReliquary(chestObject) || (Object.op_Implicit((Object)(object)managed) && !managed.OpenedByAllLocalPlayers()))
		{
			return;
		}
		PurchaseInteraction component = chestObject.GetComponent<PurchaseInteraction>();
		if (component != null)
		{
			PurchaseAvailabilityEvent onSetUnavailable = component.onSetUnavailable;
			if (onSetUnavailable != null)
			{
				((UnityEvent)onSetUnavailable).Invoke();
			}
		}
	}

	private static bool TryShowShrineDone(GameObject chestObject, ManagedChest managed)
	{
		ShrineChanceBehavior component = chestObject.GetComponent<ShrineChanceBehavior>();
		if (!Object.op_Implicit((Object)(object)component))
		{
			return false;
		}
		if ((!Object.op_Implicit((Object)(object)managed) || managed.OpenedByAllLocalPlayers()) && Object.op_Implicit((Object)(object)component.symbolTransform))
		{
			((Component)component.symbolTransform).gameObject.SetActive(false);
		}
		return true;
	}

	private static void CloseShopTerminal(ShopTerminalBehavior terminal, bool playSound)
	{
		GameObject val = (Object.op_Implicit((Object)(object)terminal.pickupDisplay) ? ((Component)terminal.pickupDisplay).gameObject : null);
		if (Object.op_Implicit((Object)(object)val) && (Object)(object)val != (Object)(object)((Component)terminal).gameObject)
		{
			val.SetActive(false);
		}
		else
		{
			terminal.HideItemDisplay(true);
		}
		Animator animator = terminal.animator;
		if (Object.op_Implicit((Object)(object)animator))
		{
			int layerIndex = animator.GetLayerIndex("Body");
			if (layerIndex >= 0 && animator.HasState(layerIndex, Animator.StringToHash("Closing")))
			{
				animator.PlayInFixedTime("Closing", layerIndex);
			}
		}
		if (playSound)
		{
			Util.PlaySound("Play_UI_tripleChestShutter", ((Component)terminal).gameObject);
		}
	}

	private static Animator FindAnimator(GameObject chestObject)
	{
		ModelLocator component = chestObject.GetComponent<ModelLocator>();
		Transform val = (Object.op_Implicit((Object)(object)component) ? component.modelTransform : null);
		if (!Object.op_Implicit((Object)(object)val))
		{
			return null;
		}
		return ((Component)val).GetComponent<Animator>();
	}

	private static IEnumerator FinishOpening(Animator animator)
	{
		yield return (object)new WaitForSeconds(1f);
		if (Object.op_Implicit((Object)(object)animator))
		{
			AnimatorBridge.Play(animator, "Body", "Opened");
		}
	}
}
internal static class CompatHooks
{
	private sealed class BeaconScope : IDisposable
	{
		private readonly bool previousActive;

		private readonly CharacterMaster previousOwner;

		private readonly Interactor previousInteractor;

		public BeaconScope(CharacterMaster owner, Interactor interactor)
		{
			previousActive = beaconContextActive;
			previousOwner = beaconOwner;
			previousInteractor = beaconInteractor;
			beaconContextActive = true;
			beaconOwner = owner;
			beaconInteractor = interactor;
		}

		public void Dispose()
		{
			beaconContextActive = previousActive;
			beaconOwner = previousOwner;
			beaconInteractor = previousInteractor;
		}
	}

	private static bool beaconContextActive;

	private static CharacterMaster beaconOwner;

	private static Interactor beaconInteractor;

	public static void Install()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Expected O, but got Unknown
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected O, but got Unknown
		UnlockTargetState.OnEnter += new hook_OnEnter(UnlockTargetState_OnEnter);
		HackingMainState.FixedUpdate += new hook_FixedUpdate(HackingMainState_FixedUpdate);
		HackingInProgressState.FixedUpdate += new hook_FixedUpdate(HackingInProgressState_FixedUpdate);
		HackingMainState.PurchaseInteractionIsValidTarget += new hook_PurchaseInteractionIsValidTarget(PurchaseInteractionIsValidTarget);
		CompulsionQuestCloakedChest.EnsureCloakedChestExists += new hook_EnsureCloakedChestExists(EnsureCloakedChestExists);
	}

	private static bool IsServerInstanced(Component component, out ManagedChest managed)
	{
		managed = (Object.op_Implicit((Object)(object)component) ? component.GetComponent<ManagedChest>() : null);
		if (NetworkServer.active && Object.op_Implicit((Object)(object)managed) && managed.serverManaged && managed.instanced)
		{
			return !managed.globallyOpened;
		}
		return false;
	}

	private static void UnlockTargetState_OnEnter(orig_OnEnter orig, UnlockTargetState self)
	{
		PurchaseInteraction target = self.target;
		int num = (Object.op_Implicit((Object)(object)target) ? target.cost : 0);
		orig.Invoke(self);
		if (num > 0 && Object.op_Implicit((Object)(object)target) && target.cost == 0 && IsServerInstanced((Component)(object)target, out var _))
		{
			target.Networkcost = num;
		}
	}

	private static void HackingMainState_FixedUpdate(orig_FixedUpdate orig, HackingMainState self)
	{
		using (BeaconContext((EntityState)(object)self))
		{
			orig.Invoke(self);
		}
	}

	private static void HackingInProgressState_FixedUpdate(orig_FixedUpdate orig, HackingInProgressState self)
	{
		using (BeaconContext((EntityState)(object)self))
		{
			orig.Invoke(self);
		}
	}

	private static bool PurchaseInteractionIsValidTarget(orig_PurchaseInteractionIsValidTarget orig, PurchaseInteraction purchaseInteraction)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		bool flag = orig.Invoke(purchaseInteraction);
		if (flag && beaconContextActive && IsServerInstanced((Component)(object)purchaseInteraction, out var managed))
		{
			if (Object.op_Implicit((Object)(object)beaconOwner) && Object.op_Implicit((Object)(object)beaconInteractor) && (int)purchaseInteraction.GetInteractability(beaconInteractor) != 0)
			{
				return !IsFreeShrineFor(managed, beaconOwner);
			}
			return false;
		}
		return flag;
	}

	private static bool IsFreeShrineFor(ManagedChest managed, CharacterMaster player)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		return (managed.IsInstancedShrine ? managed.GetShrineState(((NetworkBehaviour)player).netId, create: false) : null)?.free ?? false;
	}

	private static IDisposable BeaconContext(EntityState state)
	{
		GameObject val = (Object.op_Implicit((Object)(object)state.outer) ? ((Component)state.outer).gameObject : null);
		GenericOwnership val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<GenericOwnership>() : null);
		GameObject val3 = (Object.op_Implicit((Object)(object)val2) ? val2.ownerObject : null);
		CharacterMaster owner = PlayerResolver.FromBody(Object.op_Implicit((Object)(object)val3) ? val3.GetComponent<CharacterBody>() : null);
		Interactor interactor = (Object.op_Implicit((Object)(object)val3) ? val3.GetComponent<Interactor>() : null);
		return new BeaconScope(owner, interactor);
	}

	private static void EnsureCloakedChestExists(orig_EnsureCloakedChestExists orig, CompulsionQuestCloakedChest self)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Invalid comparison between Unknown and I4
		//IL_0036: 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_0096: Unknown result type (might be due to invalid IL or missing references)
		CompulsionQuestTracker val = (Object.op_Implicit((Object)(object)((BaseQuest)self).runner) ? ((Component)((BaseQuest)self).runner).GetComponent<CompulsionQuestTracker>() : null);
		TeamIndex team = (TeamIndex)((!Object.op_Implicit((Object)(object)val) || (int)val.participatingTeamIndex == -1) ? 1 : ((int)val.participatingTeamIndex));
		CharacterMaster questOwner = (Object.op_Implicit((Object)(object)val) ? PlayerResolver.FromBody(val.questOwnerCharacterBody) : null);
		List<ChestBehavior> list = new List<ChestBehavior>();
		foreach (ChestBehavior instances in InstanceTracker.GetInstancesList<ChestBehavior>())
		{
			if (Object.op_Implicit((Object)(object)instances) && ((Object)instances).name.IndexOf("Stealthed", StringComparison.OrdinalIgnoreCase) >= 0 && IsServerInstanced((Component)(object)instances, out var managed) && !AnyPlayerCanStillOpen(managed, team, questOwner))
			{
				list.Add(instances);
			}
		}
		List<ChestBehavior> list2 = new List<ChestBehavior>();
		try
		{
			foreach (ChestBehavior item in list)
			{
				InstanceTracker.Remove<ChestBehavior>(item);
				list2.Add(item);
			}
			orig.Invoke(self);
		}
		finally
		{
			foreach (ChestBehavior item2 in list2)
			{
				if (Object.op_Implicit((Object)(object)item2))
				{
					InstanceTracker.Add<ChestBehavior>(item2);
				}
			}
		}
	}

	private static bool AnyPlayerCanStillOpen(ManagedChest managed, TeamIndex team, CharacterMaster questOwner)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)questOwner) && managed.HasOpened(((NetworkBehaviour)questOwner).netId))
		{
			return false;
		}
		foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
		{
			if (Object.op_Implicit((Object)(object)instance) && instance.isConnected)
			{
				CharacterMaster master = instance.master;
				CharacterBody val = (Object.op_Implicit((Object)(object)master) ? master.GetBody() : null);
				bool flag = Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.healthComponent) && val.healthComponent.alive;
				if (Object.op_Implicit((Object)(object)master) && master.teamIndex == team && flag && !managed.HasOpened(((NetworkBehaviour)master).netId))
				{
					return true;
				}
			}
		}
		return false;
	}
}
internal static class Conflicts
{
	private static readonly string[] KnownConflicts = new string[8] { "ThreeChoiceChests", "ItemShare", "ShareSuite", "InstancedLoot", "ArtifactOfPotential", "Artifact of Potential", "Equilibrium", "CatchupLoot" };

	public static void WarnAboutKnownConflicts()
	{
		List<string> list = new List<string>();
		foreach (PluginInfo value2 in Chainloader.PluginInfos.Values)
		{
			string text = value2.Metadata.GUID ?? string.Empty;
			string text2 = value2.Metadata.Name ?? string.Empty;
			if (text == "com.shareitemswithmorefun")
			{
				continue;
			}
			string[] knownConflicts = KnownConflicts;
			foreach (string value in knownConflicts)
			{
				if (text2.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					list.Add(text2 + " (" + text + ")");
					break;
				}
			}
		}
		if (list.Count > 0)
		{
			Plugin.Log.LogWarning((object)("Mods qui modifient aussi les coffres ou le partage du butin : " + string.Join(", ", list) + ". Butin en double ou comportements étranges possibles : désactivez-les avec ShareItemsWithMoreFun."));
		}
	}
}
internal static class DifficultyFreeze
{
	private static GameObject freezeObject;

	public static bool IsFrozen => Object.op_Implicit((Object)(object)freezeObject);

	public static float FrozenStopwatch { get; private set; }

	public static int FrozenStageClearCount { get; private set; }

	public static void FreezeServer()
	{
		if (NetworkServer.active && Object.op_Implicit((Object)(object)Run.instance) && !IsFrozen && Apply(Run.instance.GetRunStopwatch(), Run.instance.stageClearCount))
		{
			NetMessageExtensions.Send((INetMessage)(object)new DifficultyFreezeMessage(frozen: true, FrozenStopwatch, FrozenStageClearCount), (NetworkDestination)1);
			Plugin.Debug($"Téléporteur chargé : difficulté figée à {FrozenStopwatch:0} s");
		}
	}

	public static void ReleaseServer()
	{
		if (NetworkServer.active && IsFrozen)
		{
			Release();
			NetMessageExtensions.Send((INetMessage)(object)new DifficultyFreezeMessage(frozen: false, 0f, 0), (NetworkDestination)1);
			Plugin.Debug("Difficulté relâchée");
		}
	}

	public static bool Apply(float stopwatch, int stageClearCount)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Expected O, but got Unknown
		Release();
		if (InstanceTracker.GetInstancesList<OverrideDifficultyArgs>().Count > 0)
		{
			return false;
		}
		FrozenStopwatch = stopwatch;
		FrozenStageClearCount = stageClearCount;
		freezeObject = new GameObject("ShareItemsWithMoreFun_DifficultyFreeze");
		freezeObject.SetActive(false);
		OverrideDifficultyArgs obj = freezeObject.AddComponent<OverrideDifficultyArgs>();
		obj.timeOverrideValue = Mathf.Max(0f, stopwatch);
		obj.stageClearCountOverrideValue = Mathf.Max(0, stageClearCount);
		freezeObject.SetActive(true);
		return true;
	}

	public static void Release()
	{
		if (Object.op_Implicit((Object)(object)freezeObject))
		{
			freezeObject.SetActive(false);
			Object.Destroy((Object)(object)freezeObject);
		}
		freezeObject = null;
	}
}
internal class DifficultyFreezeMessage : INetMessage, ISerializableObject
{
	private bool frozen;

	private float stopwatch;

	private int stageClearCount;

	public DifficultyFreezeMessage()
	{
	}

	public DifficultyFreezeMessage(bool frozen, float stopwatch, int stageClearCount)
	{
		this.frozen = frozen;
		this.stopwatch = stopwatch;
		this.stageClearCount = stageClearCount;
	}

	public void Serialize(NetworkWriter writer)
	{
		writer.Write(frozen);
		writer.Write(stopwatch);
		writer.Write(stageClearCount);
	}

	public void Deserialize(NetworkReader reader)
	{
		frozen = reader.ReadBoolean();
		stopwatch = reader.ReadSingle();
		stageClearCount = reader.ReadInt32();
	}

	public void OnReceived()
	{
		if (!NetworkServer.active)
		{
			if (frozen)
			{
				DifficultyFreeze.Apply(stopwatch, stageClearCount);
			}
			else
			{
				DifficultyFreeze.Release();
			}
		}
	}
}
internal sealed class DropContext : IDisposable
{
	public readonly CharacterMaster owner;

	public readonly bool convertToChoices;

	public readonly Xoroshiro128Plus rng;

	public int dropletsCreated;

	private readonly DropContext previous;

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

	public static DropContext Current { get; private set; }

	private DropContext(CharacterMaster owner, bool convertToChoices, Xoroshiro128Plus rng, DropContext previous)
	{
		this.owner = owner;
		this.convertToChoices = convertToChoices;
		this.rng = rng;
		this.previous = previous;
	}

	public static DropContext Begin(CharacterMaster owner, bool convertToChoices, Xoroshiro128Plus rng)
	{
		Current = new DropContext(owner, convertToChoices, rng, Current);
		return Current;
	}

	public void Tag(GameObject gameObject)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)owner) && Object.op_Implicit((Object)(object)gameObject))
		{
			OwnedObject.GetOrAdd(gameObject).SetOwnerServer(((NetworkBehaviour)owner).netId, ModConfig.ReserveOrbs.Value, ModConfig.HideOtherPlayersOrbs.Value, ModConfig.RemoteOpCanOpenChests.Value);
			tagged.Add(gameObject);
		}
	}

	public void Dispose()
	{
		Current = previous;
		foreach (GameObject item in tagged)
		{
			if (Object.op_Implicit((Object)(object)item))
			{
				try
				{
					OwnerMessage.Broadcast(item);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogError((object)ex);
				}
			}
		}
		tagged.Clear();
	}
}
internal static class Grant
{
	private static readonly FieldInfo PickupConsumedField = typeof(GenericPickupController).GetField("onPickupConsumed", BindingFlags.Static | BindingFlags.NonPublic);

	public static bool ToMaster(CharacterMaster master, UniquePickup pickup, Vector3 origin)
	{
		//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_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Invalid comparison between Unknown and I4
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Invalid comparison between Unknown and I4
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: 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_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: 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_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		PickupDef pickupDef = PickupCatalog.GetPickupDef(pickup.pickupIndex);
		CharacterBody val = (Object.op_Implicit((Object)(object)master) ? master.GetBody() : null);
		if (pickupDef == null || pickupDef.attemptGrant == null || !Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)master.inventory))
		{
			return false;
		}
		bool flag = (int)pickupDef.itemIndex != -1;
		bool flag2 = (int)pickupDef.equipmentIndex != -1;
		if (!flag && !flag2)
		{
			return false;
		}
		if (flag2 && val.isRemoteOp)
		{
			PendingEquipment.Add(master, pickup);
			return true;
		}
		GrantContext val2 = new GrantContext
		{
			body = val,
			controller = null
		};
		((GrantContext)(ref val2)).pickup = pickup;
		val2.position = origin;
		val2.rotation = Quaternion.identity;
		GrantContext val3 = val2;
		pickupDef.attemptGrant.Invoke(ref val3);
		val.OnPickup((PickupClass)(((UniquePickup)(ref pickup)).isTempItem ? 2 : 3));
		if (val3.shouldNotify)
		{
			GenericPickupController.SendPickupMessage(master, pickup);
		}
		if (val3.shouldDestroy)
		{
			RaisePickupConsumed(val, pickup);
		}
		if (flag)
		{
			DispatchArgs val4 = new DispatchArgs
			{
				inventoryToGrantTo = master.inventory,
				itemIndex = pickupDef.itemIndex,
				origin = origin,
				permanentCount = 0,
				temporaryCount = 0f,
				rentalCount = 0,
				travelDuration = 1f,
				isPickup = false,
				onArrivalBehavior = delegate
				{
				}
			};
			NetworkIdentity networkIdentity = val.networkIdentity;
			val4.orbDestinationOverride = Either<NetworkIdentity, HurtBox>.op_Implicit(ref networkIdentity);
			ItemTransferOrb.DispatchItemTransferOrb(val4);
		}
		else if (!val3.shouldDestroy)
		{
			UniquePickup pickup2 = ((GrantContext)(ref val3)).pickup;
			if (((UniquePickup)(ref pickup2)).isValid)
			{
				UniquePickup pickup3 = ((GrantContext)(ref val3)).pickup;
				pickup3.ignoreArtifactBasedPickupReplacements = true;
				using (DropContext.Begin(master, convertToChoices: false, null))
				{
					PickupDropletController.CreatePickupDroplet(pickup3, origin + Vector3.up, Vector3.up * 15f, false);
				}
			}
		}
		return true;
	}

	private static void RaisePickupConsumed(CharacterBody body, UniquePickup pickup)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			(PickupConsumedField?.GetValue(null) as Action<CharacterBody, UniquePickup>)?.Invoke(body, pickup);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
internal static class HexHooks
{
	private sealed class HexShares
	{
		public readonly List<PlayerCharacterMasterController> players = new List<PlayerCharacterMasterController>();

		public readonly List<int> given = new List<int>();
	}

	private const string ConceptReliquaryName = "HollowChestFree";

	private static readonly ConditionalWeakTable<GrantHexes, HexShares> shares = new ConditionalWeakTable<GrantHexes, HexShares>();

	public static void Install()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		GrantHexes.SpawnHex += new hook_SpawnHex(GrantHexes_SpawnHex);
	}

	public static bool IsConceptReliquary(GameObject gameObject)
	{
		return ModConfig.NormalizeName(((Object)gameObject).name) == "HollowChestFree";
	}

	private static void GrantHexes_SpawnHex(orig_SpawnHex orig, GrantHexes self)
	{
		if (!NetworkServer.active || !ModConfig.Enabled.Value || !ModConfig.InstancedHexes.Value)
		{
			orig.Invoke(self);
			return;
		}
		HexShares orCreateValue = shares.GetOrCreateValue(self);
		foreach (PlayerCharacterMasterController instance2 in PlayerCharacterMasterController.instances)
		{
			if (Object.op_Implicit((Object)(object)instance2) && Object.op_Implicit((Object)(object)instance2.master) && !orCreateValue.players.Contains(instance2))
			{
				orCreateValue.players.Add(instance2);
				orCreateValue.given.Add(0);
			}
		}
		int num = -1;
		for (int i = 0; i < orCreateValue.players.Count; i++)
		{
			if (Object.op_Implicit((Object)(object)orCreateValue.players[i]) && (num < 0 || orCreateValue.given[i] < orCreateValue.given[num]))
			{
				num = i;
			}
		}
		if (num < 0)
		{
			orig.Invoke(self);
			return;
		}
		orCreateValue.given[num]++;
		TeleporterInteraction instance = TeleporterInteraction.instance;
		bool reviveComing = ModConfig.ReviveDeadPlayersAfterTeleporter.Value && (!Object.op_Implicit((Object)(object)instance) || !instance.isCharged);
		CharacterMaster val = PlayerResolver.ShareOwner(orCreateValue.players[num], reviveComing);
		using (DropContext.Begin(val, convertToChoices: false, null))
		{
			orig.Invoke(self);
		}
		Plugin.Debug(string.Format("Autel sacré : maléfice pour {0} ({1} pour ce joueur)", Object.op_Implicit((Object)(object)val) ? ((Object)val).name : "tous", orCreateValue.given[num]));
	}
}
internal static class LateJoinSync
{
	public static void Install()
	{
		NetworkUser.onNetworkUserLoadedSceneServer += OnNetworkUserLoadedScene;
	}

	private static void OnNetworkUserLoadedScene(NetworkUser networkUser)
	{
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		if (!NetworkServer.active || !Object.op_Implicit((Object)(object)networkUser) || ((NetworkBehaviour)networkUser).isLocalPlayer)
		{
			return;
		}
		NetworkConnection connectionToClient = ((NetworkBehaviour)networkUser).connectionToClient;
		if (connectionToClient == null || NetworkServer.localConnections.Contains(connectionToClient))
		{
			return;
		}
		int num = 0;
		if (DifficultyFreeze.IsFrozen)
		{
			NetMessageExtensions.Send((INetMessage)(object)new DifficultyFreezeMessage(frozen: true, DifficultyFreeze.FrozenStopwatch, DifficultyFreeze.FrozenStageClearCount), connectionToClient);
			num++;
		}
		foreach (ManagedChest item in new List<ManagedChest>(ManagedChest.Instances))
		{
			if (!Object.op_Implicit((Object)(object)item) || !item.serverManaged || !item.instanced || item.globallyOpened || !Object.op_Implicit((Object)(object)item.purchase))
			{
				continue;
			}
			ChestManagedMessage chestManagedMessage = ChestManagedMessage.For(item);
			if (chestManagedMessage != null)
			{
				NetMessageExtensions.Send((INetMessage)(object)chestManagedMessage, connectionToClient);
				num++;
			}
			foreach (NetworkInstanceId item2 in item.OpenedBy)
			{
				NetMessageExtensions.Send((INetMessage)(object)new ChestOpenedMessage(((NetworkBehaviour)item.purchase).netId, item2, ChestVisual.ShowOpened), connectionToClient);
				num++;
			}
			foreach (KeyValuePair<NetworkInstanceId, ShrinePlayerState> shrineState in item.ShrineStates)
			{
				NetMessageExtensions.Send((INetMessage)(object)new ShrineStateMessage(((NetworkBehaviour)item.purchase).netId, shrineState.Key, shrineState.Value, cooldown: false), connectionToClient);
				num++;
			}
			if (item.marked)
			{
				NetMessageExtensions.Send((INetMessage)(object)new ChestMarkedMessage(((NetworkBehaviour)item.purchase).netId), connectionToClient);
				num++;
			}
		}
		foreach (OwnedObject item3 in new List<OwnedObject>(OwnedObject.Instances))
		{
			OwnerMessage ownerMessage = (Object.op_Implicit((Object)(object)item3) ? OwnerMessage.For(((Component)item3).gameObject) : null);
			if (ownerMessage != null)
			{
				NetMessageExtensions.Send((INetMessage)(object)ownerMessage, connectionToClient);
				num++;
			}
		}
		Plugin.Debug($"État envoyé à {networkUser.userName} ({num} message(s))");
	}
}
internal class ManagedChest : MonoBehaviour
{
	public static readonly HashSet<ManagedChest> Instances = new HashSet<ManagedChest>();

	public bool instanced;

	public bool serverManaged;

	public bool globallyOpened;

	public bool remoteOpAllowed;

	public ChestBehavior chest;

	public OptionChestBehavior optionChest;

	public bool isShopTerminal;

	public MultiShopController shop;

	public bool keepShopOpen;

	public PurchaseInteraction purchase;

	public int baseDropCount = 1;

	public bool neverConvert;

	public Xoroshiro128Plus rng;

	public bool purchaseInProgress;

	public bool purchaseSucceeded;

	public bool allowItemDrop;

	public bool localOpenedShown;

	public bool marked;

	public ShrineChanceBehavior shrine;

	public CharacterMaster shrinePlayer;

	public bool shrineSucceeded;

	private readonly HashSet<NetworkInstanceId> openedBy = new HashSet<NetworkInstanceId>();

	private readonly Dictionary<NetworkInstanceId, ShrinePlayerState> shrineStates = new Dictionary<NetworkInstanceId, ShrinePlayerState>();

	public IEnumerable<NetworkInstanceId> OpenedBy => openedBy;

	public IEnumerable<KeyValuePair<NetworkInstanceId, ShrinePlayerState>> ShrineStates => shrineStates;

	public bool IsInstancedShrine
	{
		get
		{
			if (Object.op_Implicit((Object)(object)shrine) && instanced)
			{
				return !globallyOpened;
			}
			return false;
		}
	}

	public ShrinePlayerState GetShrineState(NetworkInstanceId masterId, bool create)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		if (!shrineStates.TryGetValue(masterId, out var value) && create)
		{
			value = new ShrinePlayerState();
			shrineStates[masterId] = value;
		}
		return value;
	}

	public bool ShrineUsableByAnyLocalPlayer()
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		bool flag = false;
		foreach (LocalUser readOnlyLocalUsers in LocalUserManager.readOnlyLocalUsersList)
		{
			CharacterMaster cachedMaster = readOnlyLocalUsers.cachedMaster;
			if (Object.op_Implicit((Object)(object)cachedMaster))
			{
				flag = true;
				if (!openedBy.Contains(((NetworkBehaviour)cachedMaster).netId) && !IsShrineCoolingDown(cachedMaster))
				{
					return true;
				}
			}
		}
		return !flag;
	}

	public bool IsShrineCoolingDown(CharacterMaster player)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		if (!IsInstancedShrine || !Object.op_Implicit((Object)(object)player))
		{
			return false;
		}
		ShrinePlayerState shrineState = GetShrineState(((NetworkBehaviour)player).netId, create: false);
		if (shrineState != null)
		{
			return Time.time < shrineState.readyTime;
		}
		return false;
	}

	public bool IsInstancedFor(Interactor activator, out bool alreadyOpened)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		alreadyOpened = false;
		if (!instanced || globallyOpened)
		{
			return false;
		}
		CharacterMaster val = PlayerResolver.FromInteractor(activator);
		alreadyOpened = !Object.op_Implicit((Object)(object)val) || openedBy.Contains(((NetworkBehaviour)val).netId);
		return true;
	}

	public bool HasOpened(NetworkInstanceId masterId)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		return openedBy.Contains(masterId);
	}

	public void MarkOpened(NetworkInstanceId masterId)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		openedBy.Add(masterId);
	}

	public bool OpenedByAnyLocalPlayer()
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		if (!instanced || globallyOpened)
		{
			return false;
		}
		foreach (NetworkInstanceId item in openedBy)
		{
			if (PlayerResolver.IsLocalPlayer(item))
			{
				return true;
			}
		}
		return false;
	}

	public bool OpenedByAllLocalPlayers()
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		if (!instanced || globallyOpened || LocalUserManager.readOnlyLocalUsersList.Count == 0)
		{
			return false;
		}
		foreach (LocalUser readOnlyLocalUsers in LocalUserManager.readOnlyLocalUsersList)
		{
			CharacterMaster cachedMaster = readOnlyLocalUsers.cachedMaster;
			if (!Object.op_Implicit((Object)(object)cachedMaster) || !openedBy.Contains(((NetworkBehaviour)cachedMaster).netId))
			{
				return false;
			}
		}
		return true;
	}

	public static ManagedChest GetOrAdd(GameObject chestObject)
	{
		ManagedChest managedChest = chestObject.GetComponent<ManagedChest>();
		if (!Object.op_Implicit((Object)(object)managedChest))
		{
			managedChest = chestObject.AddComponent<ManagedChest>();
			managedChest.shrine = chestObject.GetComponent<ShrineChanceBehavior>();
		}
		return managedChest;
	}

	private void OnEnable()
	{
		Instances.Add(this);
	}

	private void OnDisable()
	{
		Instances.Remove(this);
	}
}
internal sealed class ShrinePlayerState
{
	public int attempts;

	public int successes;

	public float readyTime;

	public bool free;
}
internal enum ChestVisual : byte
{
	None,
	PlayOpening,
	ShowOpened
}
internal class ChestManagedMessage : INetMessage, ISerializableObject
{
	private NetworkInstanceId chestId;

	private bool remoteOpAllowed;

	public static ChestManagedMessage For(ManagedChest managed)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)managed) && Object.op_Implicit((Object)(object)managed.purchase))
		{
			NetworkInstanceId netId = ((NetworkBehaviour)managed.purchase).netId;
			if (!((NetworkInstanceId)(ref netId)).IsEmpty())
			{
				return new ChestManagedMessage
				{
					chestId = ((NetworkBehaviour)managed.purchase).netId,
					remoteOpAllowed = managed.remoteOpAllowed
				};
			}
		}
		return null;
	}

	public void Serialize(NetworkWriter writer)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		writer.Write(chestId);
		writer.Write(remoteOpAllowed);
	}

	public void Deserialize(NetworkReader reader)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		chestId = reader.ReadNetworkId();
		remoteOpAllowed = reader.ReadBoolean();
	}

	public void OnReceived()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		if (!NetworkServer.active)
		{
			bool allowed = remoteOpAllowed;
			NetworkLookups.WhenFound(chestId, delegate(GameObject chestObject)
			{
				ManagedChest orAdd = ManagedChest.GetOrAdd(chestObject);
				orAdd.instanced = true;
				orAdd.remoteOpAllowed = allowed;
			});
		}
	}
}
internal class ChestOpenedMessage : INetMessage, ISerializableObject
{
	private NetworkInstanceId chestId;

	private NetworkInstanceId playerId;

	private ChestVisual visual;

	public ChestOpenedMessage()
	{
	}

	public ChestOpenedMessage(NetworkInstanceId chestId, NetworkInstanceId playerId, ChestVisual visual)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		this.chestId = chestId;
		this.playerId = playerId;
		this.visual = visual;
	}

	public void Serialize(NetworkWriter writer)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		writer.Write(chestId);
		writer.Write(playerId);
		writer.Write((byte)visual);
	}

	public void Deserialize(NetworkReader reader)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		chestId = reader.ReadNetworkId();
		playerId = reader.ReadNetworkId();
		visual = (ChestVisual)reader.ReadByte();
	}

	public void OnReceived()
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		NetworkInstanceId player = playerId;
		ChestVisual chestVisual = visual;
		NetworkLookups.WhenFound(chestId, delegate(GameObject chestObject)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			ManagedChest orAdd = ManagedChest.GetOrAdd(chestObject);
			orAdd.instanced = true;
			bool flag = !orAdd.HasOpened(player);
			orAdd.MarkOpened(player);
			if (PlayerResolver.IsLocalPlayer(player))
			{
				if (chestVisual == ChestVisual.PlayOpening)
				{
					ClientVisuals.PlayLocalOpening(chestObject);
				}
				else if (chestVisual == ChestVisual.ShowOpened && (flag || !orAdd.localOpenedShown))
				{
					ClientVisuals.ShowOpened(chestObject);
				}
			}
		});
	}
}
internal class ChestMarkedMessage : INetMessage, ISerializableObject
{
	private NetworkInstanceId chestId;

	public ChestMarkedMessage()
	{
	}

	public ChestMarkedMessage(NetworkInstanceId chestId)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		this.chestId = chestId;
	}

	public void Serialize(NetworkWriter writer)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		writer.Write(chestId);
	}

	public void Deserialize(NetworkReader reader)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		chestId = reader.ReadNetworkId();
	}

	public void OnReceived()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		NetworkLookups.WhenFound(chestId, delegate(GameObject chestObject)
		{
			ManagedChest orAdd = ManagedChest.GetOrAdd(chestObject);
			orAdd.instanced = true;
			orAdd.marked = true;
		});
	}
}
internal class ShrineStateMessage : INetMessage, ISerializableObject
{
	private NetworkInstanceId shrineId;

	private NetworkInstanceId playerId;

	private int attempts;

	private int successes;

	private bool free;

	private bool cooldown;

	public ShrineStateMessage()
	{
	}

	public ShrineStateMessage(NetworkInstanceId shrineId, NetworkInstanceId playerId, ShrinePlayerState state, bool cooldown)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		this.shrineId = shrineId;
		this.playerId = playerId;
		attempts = state.attempts;
		successes = state.successes;
		free = state.free;
		this.cooldown = cooldown;
	}

	public void Serialize(NetworkWriter writer)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		writer.Write(shrineId);
		writer.Write(playerId);
		writer.WritePackedUInt32((uint)attempts);
		writer.WritePackedUInt32((uint)successes);
		writer.Write(free);
		writer.Write(cooldown);
	}

	public void Deserialize(NetworkReader reader)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		shrineId = reader.ReadNetworkId();
		playerId = reader.ReadNetworkId();
		attempts = (int)reader.ReadPackedUInt32();
		successes = (int)reader.ReadPackedUInt32();
		free = reader.ReadBoolean();
		cooldown = reader.ReadBoolean();
	}

	public void OnReceived()
	{
		//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_004b: Unknown result type (might be due to invalid IL or missing references)
		if (NetworkServer.active)
		{
			return;
		}
		NetworkInstanceId player = playerId;
		int playerAttempts = attempts;
		int playerSuccesses = successes;
		bool playerFree = free;
		bool startCooldown = cooldown;
		NetworkLookups.WhenFound(shrineId, delegate(GameObject shrineObject)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			ManagedChest orAdd = ManagedChest.GetOrAdd(shrineObject);
			orAdd.instanced = true;
			ShrinePlayerState shrineState = orAdd.GetShrineState(player, create: true);
			shrineState.attempts = playerAttempts;
			shrineState.successes = playerSuccesses;
			shrineState.free = playerFree;
			if (startCooldown)
			{
				shrineState.readyTime = Time.time