Decompiled source of ItemShare v1.7.1

ItemShare.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using On.RoR2;
using PickupShare;
using R2API.Networking;
using R2API.Networking.Interfaces;
using R2API.Utils;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ItemShare")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.7.1.0")]
[assembly: AssemblyInformationalVersion("1.7.1")]
[assembly: AssemblyProduct("ItemShare")]
[assembly: AssemblyTitle("ItemShare")]
[assembly: AssemblyVersion("1.7.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ItemShare
{
	internal sealed class PickRecord
	{
		private readonly Dictionary<uint, HashSet<uint>> _picks = new Dictionary<uint, HashSet<uint>>();

		public void Apply(uint dropNetId, uint[] masterNetIds)
		{
			if (masterNetIds == null || masterNetIds.Length == 0)
			{
				_picks.Remove(dropNetId);
				return;
			}
			HashSet<uint> hashSet = new HashSet<uint>();
			foreach (uint item in masterNetIds)
			{
				hashSet.Add(item);
			}
			_picks[dropNetId] = hashSet;
		}

		public bool Contains(uint dropNetId, uint masterNetId)
		{
			if (_picks.TryGetValue(dropNetId, out var value))
			{
				return value.Contains(masterNetId);
			}
			return false;
		}

		public void Clear()
		{
			_picks.Clear();
		}
	}
	internal static class ClientPickMirror
	{
		public static readonly PickRecord Cubes = new PickRecord();

		public static readonly PickRecord Orbs = new PickRecord();

		public static void Clear()
		{
			Cubes.Clear();
			Orbs.Clear();
		}
	}
	internal enum PickKind : byte
	{
		Orb,
		CommandCube
	}
	public sealed class PickStateMessage : INetMessage, ISerializableObject
	{
		private byte _kind;

		private NetworkInstanceId _dropNetId;

		private uint[] _masterNetIds;

		public PickStateMessage()
		{
		}

		internal PickStateMessage(PickKind kind, NetworkInstanceId dropNetId, uint[] masterNetIds)
		{
			//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)
			_kind = (byte)kind;
			_dropNetId = dropNetId;
			_masterNetIds = masterNetIds;
		}

		public void Serialize(NetworkWriter writer)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			writer.Write(_kind);
			writer.Write(_dropNetId);
			writer.Write((uint)_masterNetIds.Length);
			uint[] masterNetIds = _masterNetIds;
			foreach (uint num in masterNetIds)
			{
				writer.Write(num);
			}
		}

		public void Deserialize(NetworkReader reader)
		{
			//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)
			_kind = reader.ReadByte();
			_dropNetId = reader.ReadNetworkId();
			uint num = reader.ReadUInt32();
			_masterNetIds = new uint[num];
			for (int i = 0; i < num; i++)
			{
				_masterNetIds[i] = reader.ReadUInt32();
			}
		}

		public void OnReceived()
		{
			if (!NetworkServer.active)
			{
				if (_kind == 1)
				{
					ClientPickMirror.Cubes.Apply(((NetworkInstanceId)(ref _dropNetId)).Value, _masterNetIds);
					return;
				}
				ClientPickMirror.Orbs.Apply(((NetworkInstanceId)(ref _dropNetId)).Value, _masterNetIds);
				ItemSharePlugin.RefreshOrbVisibility();
			}
		}
	}
	public enum PickupMode
	{
		Instant,
		Individual
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.majai.itemshare", "ItemShare", "1.7.1")]
	public class ItemSharePlugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_AttemptGrant <0>__OnAttemptGrant;

			public static hook_HandlePickupSelected <1>__OnPickupSelected;

			public static hook_OnInteractionBegin <2>__OnPickerInteractionBegin;

			public static hook_GetInteractability <3>__OnPickerInteractability;

			public static hook_CmdPing <4>__OnPing;

			public static Action<Stage> <5>__OnStageStart;
		}

		public const string Guid = "com.majai.itemshare";

		public const string Name = "ItemShare";

		public const string Version = "1.7.1";

		internal static ManualLogSource Log;

		private static ConfigEntry<PickupMode> _mode;

		private static readonly ItemShareStateProvider StateProvider = new ItemShareStateProvider();

		private static ConfigEntry<bool> _shareTier1;

		private static ConfigEntry<bool> _shareTier2;

		private static ConfigEntry<bool> _shareTier3;

		private static ConfigEntry<bool> _shareBoss;

		private static ConfigEntry<bool> _shareLunar;

		private static ConfigEntry<bool> _shareVoid;

		private static ConfigEntry<bool> _shareFood;

		private static ConfigEntry<bool> _shareEquipment;

		private static ConfigEntry<bool> _shareToDead;

		private static ConfigEntry<bool> _announce;

		private static ConfigEntry<bool> _shareCommandPicks;

		private static ConfigEntry<bool> _pingShowsPending;

		private static ConfigEntry<bool> _silenceRemoteNotificationErrors;

		private static ConfigEntry<bool> _hideCollectedOrbs;

		internal static readonly HashSet<int> Distributed = new HashSet<int>();

		internal static readonly Dictionary<int, HashSet<CharacterMaster>> Claims = new Dictionary<int, HashSet<CharacterMaster>>();

		internal static readonly Dictionary<int, HashSet<CharacterMaster>> Choices = new Dictionary<int, HashSet<CharacterMaster>>();

		private static readonly List<CharacterMaster> Buffer = new List<CharacterMaster>();

		private static bool _cubeSyncDirty;

		private static Harmony _harmony;

		private static readonly HashSet<int> HiddenOrbs = new HashSet<int>();

		private static readonly List<CharacterMaster> LocalMasters = new List<CharacterMaster>();

		private static readonly List<Renderer> RendererBuffer = new List<Renderer>();

		private static readonly List<Light> LightBuffer = new List<Light>();

		private static float _nextOrbVisibilitySweep;

		public void Awake()
		{
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Expected O, but got Unknown
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Expected O, but got Unknown
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Expected O, but got Unknown
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			_mode = ((BaseUnityPlugin)this).Config.Bind<PickupMode>("General", "PickupMode", PickupMode.Individual, "Individual: everyone walks over the orb themselves, it despawns once the last player has it.\nInstant: the first player to touch it takes it and everyone else is given a copy on the spot.");
			_shareTier1 = ((BaseUnityPlugin)this).Config.Bind<bool>("Tiers", "White", true, "Share Tier 1 (white) items.");
			_shareTier2 = ((BaseUnityPlugin)this).Config.Bind<bool>("Tiers", "Green", true, "Share Tier 2 (green) items.");
			_shareTier3 = ((BaseUnityPlugin)this).Config.Bind<bool>("Tiers", "Red", true, "Share Tier 3 (red) items.");
			_shareBoss = ((BaseUnityPlugin)this).Config.Bind<bool>("Tiers", "Boss", true, "Share boss (yellow) items.");
			_shareLunar = ((BaseUnityPlugin)this).Config.Bind<bool>("Tiers", "Lunar", false, "Share lunar (blue) items.");
			_shareVoid = ((BaseUnityPlugin)this).Config.Bind<bool>("Tiers", "Void", false, "Share void items. Warning: void items corrupt their counterpart, so everyone loses the corrupted item.");
			_shareFood = ((BaseUnityPlugin)this).Config.Bind<bool>("Tiers", "Food", false, "Share FoodTier items. Off by default only because this tier is untested here - flip it on if you want it shared.");
			_shareEquipment = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShareEquipment", false, "Instant mode only. Gives equipment to other players, but only if they have a free equipment slot. Ignored in Individual mode, where equipment orbs stay vanilla.");
			_shareToDead = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShareToDead", true, "Dead players are handed the item automatically, since they cannot walk over the orb. Either way a dead player never blocks the orb from despawning.");
			_announce = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AnnounceProgress", true, "Individual mode only. Post a chat line showing how many players have collected each orb.");
			_shareCommandPicks = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShareCommandPicks", true, "Individual mode only. With Artifact of Command, every player opens the cube and picks their own item instead of the first chooser deciding for everyone. The cube stays until all have picked.");
			_pingShowsPending = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PingShowsPending", true, "Individual mode only. Pinging a drop or a Command cube that somebody has already taken posts the names of the players who still have not.");
			_hideCollectedOrbs = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HideCollectedOrbs", true, "Individual mode only. Once you have collected a drop it stops being drawn for you, while staying visible to everyone who still needs it. Useful where drops end up clustered - a pile you are finished with no longer hides the one you are not. Turn it off to keep every drop visible until it despawns.");
			_silenceRemoteNotificationErrors = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SilenceRemoteNotificationErrors", true, "Suppresses the vanilla \"Can't PushPickupNotification for X because they aren't local\" error. It is logged for a completely normal condition, and this mod makes it far more frequent. Turn it off only if you suspect the patch of hiding something.");
			NetworkingAPI.RegisterMessageType<PickStateMessage>();
			ApplyNotificationSpamPatch();
			object obj = <>O.<0>__OnAttemptGrant;
			if (obj == null)
			{
				hook_AttemptGrant val = OnAttemptGrant;
				<>O.<0>__OnAttemptGrant = val;
				obj = (object)val;
			}
			GenericPickupController.AttemptGrant += (hook_AttemptGrant)obj;
			object obj2 = <>O.<1>__OnPickupSelected;
			if (obj2 == null)
			{
				hook_HandlePickupSelected val2 = OnPickupSelected;
				<>O.<1>__OnPickupSelected = val2;
				obj2 = (object)val2;
			}
			PickupPickerController.HandlePickupSelected += (hook_HandlePickupSelected)obj2;
			object obj3 = <>O.<2>__OnPickerInteractionBegin;
			if (obj3 == null)
			{
				hook_OnInteractionBegin val3 = OnPickerInteractionBegin;
				<>O.<2>__OnPickerInteractionBegin = val3;
				obj3 = (object)val3;
			}
			PickupPickerController.OnInteractionBegin += (hook_OnInteractionBegin)obj3;
			object obj4 = <>O.<3>__OnPickerInteractability;
			if (obj4 == null)
			{
				hook_GetInteractability val4 = OnPickerInteractability;
				<>O.<3>__OnPickerInteractability = val4;
				obj4 = (object)val4;
			}
			PickupPickerController.GetInteractability += (hook_GetInteractability)obj4;
			object obj5 = <>O.<4>__OnPing;
			if (obj5 == null)
			{
				hook_CmdPing val5 = OnPing;
				<>O.<4>__OnPing = val5;
				obj5 = (object)val5;
			}
			PingerController.CmdPing += (hook_CmdPing)obj5;
			Stage.onStageStartGlobal += OnStageStart;
			PickupShareApi.RegisterProvider((IPickupStateProvider)(object)StateProvider);
			Log.LogInfo((object)string.Format("{0} {1} loaded in {2} mode.", "ItemShare", "1.7.1", _mode.Value));
		}

		public void OnDestroy()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//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_005b: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			object obj = <>O.<0>__OnAttemptGrant;
			if (obj == null)
			{
				hook_AttemptGrant val = OnAttemptGrant;
				<>O.<0>__OnAttemptGrant = val;
				obj = (object)val;
			}
			GenericPickupController.AttemptGrant -= (hook_AttemptGrant)obj;
			object obj2 = <>O.<1>__OnPickupSelected;
			if (obj2 == null)
			{
				hook_HandlePickupSelected val2 = OnPickupSelected;
				<>O.<1>__OnPickupSelected = val2;
				obj2 = (object)val2;
			}
			PickupPickerController.HandlePickupSelected -= (hook_HandlePickupSelected)obj2;
			object obj3 = <>O.<2>__OnPickerInteractionBegin;
			if (obj3 == null)
			{
				hook_OnInteractionBegin val3 = OnPickerInteractionBegin;
				<>O.<2>__OnPickerInteractionBegin = val3;
				obj3 = (object)val3;
			}
			PickupPickerController.OnInteractionBegin -= (hook_OnInteractionBegin)obj3;
			object obj4 = <>O.<3>__OnPickerInteractability;
			if (obj4 == null)
			{
				hook_GetInteractability val4 = OnPickerInteractability;
				<>O.<3>__OnPickerInteractability = val4;
				obj4 = (object)val4;
			}
			PickupPickerController.GetInteractability -= (hook_GetInteractability)obj4;
			object obj5 = <>O.<4>__OnPing;
			if (obj5 == null)
			{
				hook_CmdPing val5 = OnPing;
				<>O.<4>__OnPing = val5;
				obj5 = (object)val5;
			}
			PingerController.CmdPing -= (hook_CmdPing)obj5;
			Stage.onStageStartGlobal -= OnStageStart;
			PickupShareApi.UnregisterProvider((IPickupStateProvider)(object)StateProvider);
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private static void OnStageStart(Stage stage)
		{
			ClientPickMirror.Clear();
			HiddenOrbs.Clear();
			Distributed.Clear();
			Claims.Clear();
			Choices.Clear();
		}

		private static void OnAttemptGrant(orig_AttemptGrant orig, GenericPickupController self, CharacterBody body)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || (Object)(object)body == (Object)null || (Object)(object)body.master == (Object)null)
			{
				orig.Invoke(self, body);
				return;
			}
			UniquePickup pickup = self.pickup;
			PickupDef pickupDef = PickupCatalog.GetPickupDef(pickup.pickupIndex);
			if (pickupDef == null || !IsShareable(pickupDef))
			{
				orig.Invoke(self, body);
			}
			else if (_mode.Value == PickupMode.Individual)
			{
				GrantIndividual(orig, self, body, pickupDef, pickup);
			}
			else
			{
				GrantInstant(orig, self, body, pickupDef, pickup);
			}
		}

		private static void GrantInstant(orig_AttemptGrant orig, GenericPickupController self, CharacterBody body, PickupDef def, UniquePickup pickup)
		{
			//IL_008c: 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)
			if (!Distributed.Add(((Object)self).GetInstanceID()))
			{
				orig.Invoke(self, body);
				return;
			}
			CharacterMaster master = body.master;
			orig.Invoke(self, body);
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				CharacterMaster val = (((Object)(object)instance != (Object)null) ? instance.master : null);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)master) && !((Object)(object)val.inventory == (Object)null) && (_shareToDead.Value || !IsDown(val)) && GiveDirect(val.inventory, def, pickup))
				{
					GenericPickupController.SendPickupMessage(val, pickup);
				}
			}
		}

		private static void GrantIndividual(orig_AttemptGrant orig, GenericPickupController self, CharacterBody body, PickupDef def, UniquePickup pickup)
		{
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)self).GetInstanceID();
			CharacterMaster master = body.master;
			if (!Claims.TryGetValue(instanceID, out var value))
			{
				value = new HashSet<CharacterMaster>();
				Claims[instanceID] = value;
			}
			if (value.Contains(master))
			{
				return;
			}
			if (_shareToDead.Value)
			{
				foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
				{
					CharacterMaster val = (((Object)(object)instance != (Object)null) ? instance.master : null);
					if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)master) && !((Object)(object)val.inventory == (Object)null) && IsDown(val) && value.Add(val) && GiveDirect(val.inventory, def, pickup))
					{
						GenericPickupController.SendPickupMessage(val, pickup);
					}
				}
			}
			value.Add(master);
			BroadcastOrbState(self, value);
			RefreshOrbVisibility();
			Collectors(Buffer);
			bool flag = true;
			foreach (CharacterMaster item in Buffer)
			{
				if (!value.Contains(item))
				{
					flag = false;
					break;
				}
			}
			if (flag)
			{
				Claims.Remove(instanceID);
				orig.Invoke(self, body);
			}
			else
			{
				GrantWithoutDespawning(self, body, def, pickup);
				Announce(master, value, Buffer);
			}
		}

		private static void GrantWithoutDespawning(GenericPickupController self, CharacterBody body, PickupDef def, UniquePickup pickup)
		{
			//IL_0009: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			PickupDisplay pickupDisplay = self.pickupDisplay;
			GrantContext val = new GrantContext
			{
				body = body,
				controller = self,
				position = (((Object)(object)pickupDisplay != (Object)null) ? ((Component)pickupDisplay).transform.position : ((Component)self).transform.position),
				rotation = (((Object)(object)pickupDisplay != (Object)null) ? ((Component)pickupDisplay).transform.rotation : Quaternion.identity)
			};
			AttemptGrantDelegate attemptGrant = def.attemptGrant;
			if (attemptGrant != null)
			{
				attemptGrant.Invoke(ref val);
			}
			body.OnPickup((PickupClass)(((UniquePickup)(ref pickup)).isTempItem ? 2 : 3));
			if (val.shouldNotify)
			{
				GenericPickupController.SendPickupMessage(body.master, pickup);
			}
		}

		private static void OnPickupSelected(orig_HandlePickupSelected orig, PickupPickerController self, int choiceIndex)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!NetworkServer.active || !CommandTakeoverActive(self))
			{
				orig.Invoke(self, choiceIndex);
				return;
			}
			if (self.options == null || choiceIndex < 0 || choiceIndex >= self.options.Length)
			{
				orig.Invoke(self, choiceIndex);
				return;
			}
			Option val = self.options[choiceIndex];
			if (!val.available)
			{
				orig.Invoke(self, choiceIndex);
				return;
			}
			PickupDef pickupDef = PickupCatalog.GetPickupDef(val.pickup.pickupIndex);
			if (pickupDef == null || !IsShareable(pickupDef))
			{
				orig.Invoke(self, choiceIndex);
				return;
			}
			NetworkUIPromptController component = ((Component)self).GetComponent<NetworkUIPromptController>();
			CharacterMaster val2 = (((Object)(object)component != (Object)null) ? component.currentParticipantMaster : null);
			if ((Object)(object)val2 == (Object)null || (Object)(object)val2.inventory == (Object)null)
			{
				orig.Invoke(self, choiceIndex);
				return;
			}
			int instanceID = ((Object)self).GetInstanceID();
			if (!Choices.TryGetValue(instanceID, out var value))
			{
				value = new HashSet<CharacterMaster>();
				Choices[instanceID] = value;
			}
			bool num = value.Add(val2);
			if (num)
			{
				GiveDirect(val2.inventory, pickupDef, val.pickup);
				GenericPickupController.SendPickupMessage(val2, val.pickup);
				BroadcastCubeState(self, value);
			}
			component.SetParticipantMaster((CharacterMaster)null);
			if (!num)
			{
				return;
			}
			Collectors(Buffer);
			bool flag = true;
			foreach (CharacterMaster item in Buffer)
			{
				if (!value.Contains(item))
				{
					flag = false;
					break;
				}
			}
			if (flag)
			{
				Choices.Remove(instanceID);
				Object.Destroy((Object)(object)((Component)self).gameObject);
			}
			else
			{
				Announce(val2, value, Buffer);
			}
		}

		private void ApplyNotificationSpamPatch()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			if (_silenceRemoteNotificationErrors.Value)
			{
				MethodInfo method = typeof(CharacterMasterNotificationQueue).GetMethod("PushPickupNotification", BindingFlags.Static | BindingFlags.Public, null, new Type[4]
				{
					typeof(CharacterMaster),
					typeof(PickupIndex),
					typeof(bool),
					typeof(int)
				}, null);
				if (method == null)
				{
					Log.LogWarning((object)"Could not find CharacterMasterNotificationQueue.PushPickupNotification, so the pickup notification spam is not patched. Harmless, just noisy logs.");
					return;
				}
				_harmony = new Harmony("com.majai.itemshare");
				_harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(ItemSharePlugin).GetMethod("SkipNotificationForRemoteMaster", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static bool SkipNotificationForRemoteMaster(CharacterMaster characterMaster)
		{
			if (!((Object)(object)characterMaster == (Object)null))
			{
				return ((NetworkBehaviour)characterMaster).hasAuthority;
			}
			return true;
		}

		private static void BroadcastCubeState(PickupPickerController cube, HashSet<CharacterMaster> chosen)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || (Object)(object)cube == (Object)null)
			{
				return;
			}
			uint[] array = new uint[chosen.Count];
			int num = 0;
			foreach (CharacterMaster item in chosen)
			{
				if ((Object)(object)item != (Object)null)
				{
					uint[] array2 = array;
					int num2 = num++;
					NetworkInstanceId netId = ((NetworkBehaviour)item).netId;
					array2[num2] = ((NetworkInstanceId)(ref netId)).Value;
				}
			}
			if (num != array.Length)
			{
				Array.Resize(ref array, num);
			}
			NetMessageExtensions.Send((INetMessage)(object)new PickStateMessage(PickKind.CommandCube, ((NetworkBehaviour)cube).netId, array), (NetworkDestination)1);
		}

		private static void BroadcastOrbState(GenericPickupController orb, HashSet<CharacterMaster> claimed)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active && !((Object)(object)orb == (Object)null))
			{
				NetMessageExtensions.Send((INetMessage)(object)new PickStateMessage(PickKind.Orb, ((NetworkBehaviour)orb).netId, MasterNetIds(claimed)), (NetworkDestination)1);
			}
		}

		private static uint[] MasterNetIds(HashSet<CharacterMaster> masters)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			uint[] array = new uint[masters.Count];
			int num = 0;
			foreach (CharacterMaster master in masters)
			{
				if ((Object)(object)master != (Object)null)
				{
					uint[] array2 = array;
					int num2 = num++;
					NetworkInstanceId netId = ((NetworkBehaviour)master).netId;
					array2[num2] = ((NetworkInstanceId)(ref netId)).Value;
				}
			}
			if (num != array.Length)
			{
				Array.Resize(ref array, num);
			}
			return array;
		}

		internal static void RefreshOrbVisibility()
		{
			if (_hideCollectedOrbs == null || !_hideCollectedOrbs.Value || _mode.Value != PickupMode.Individual)
			{
				RestoreHiddenOrbs();
				return;
			}
			LocalMasters.Clear();
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				CharacterMaster val = (((Object)(object)instance != (Object)null) ? instance.master : null);
				if ((Object)(object)val != (Object)null && ((NetworkBehaviour)val).hasAuthority)
				{
					LocalMasters.Add(val);
				}
			}
			if (LocalMasters.Count == 0)
			{
				RestoreHiddenOrbs();
				return;
			}
			foreach (GenericPickupController instances in InstanceTracker.GetInstancesList<GenericPickupController>())
			{
				if ((Object)(object)instances == (Object)null || (Object)(object)instances.pickupDisplay == (Object)null)
				{
					continue;
				}
				int instanceID = ((Object)instances).GetInstanceID();
				bool flag = LocalPlayersHaveTaken(instances);
				if (flag || HiddenOrbs.Contains(instanceID))
				{
					ApplyOrbVisibility(instances, !flag);
					if (flag)
					{
						HiddenOrbs.Add(instanceID);
					}
					else
					{
						HiddenOrbs.Remove(instanceID);
					}
				}
			}
		}

		private static void ApplyOrbVisibility(GenericPickupController orb, bool visible)
		{
			PickupDisplay pickupDisplay = orb.pickupDisplay;
			if ((Object)(object)pickupDisplay == (Object)null)
			{
				return;
			}
			pickupDisplay.SetRenderersEnabled(visible);
			((Component)pickupDisplay).GetComponentsInChildren<Renderer>(true, RendererBuffer);
			foreach (Renderer item in RendererBuffer)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.forceRenderingOff = !visible;
				}
			}
			((Component)pickupDisplay).GetComponentsInChildren<Light>(true, LightBuffer);
			foreach (Light item2 in LightBuffer)
			{
				if ((Object)(object)item2 != (Object)null)
				{
					((Behaviour)item2).enabled = visible;
				}
			}
		}

		private static bool LocalPlayersHaveTaken(GenericPickupController orb)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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)
			if (NetworkServer.active)
			{
				if (!Claims.TryGetValue(((Object)orb).GetInstanceID(), out var value))
				{
					return false;
				}
				foreach (CharacterMaster localMaster in LocalMasters)
				{
					if (!value.Contains(localMaster))
					{
						return false;
					}
				}
				return true;
			}
			NetworkInstanceId netId = ((NetworkBehaviour)orb).netId;
			uint value2 = ((NetworkInstanceId)(ref netId)).Value;
			foreach (CharacterMaster localMaster2 in LocalMasters)
			{
				PickRecord orbs = ClientPickMirror.Orbs;
				netId = ((NetworkBehaviour)localMaster2).netId;
				if (!orbs.Contains(value2, ((NetworkInstanceId)(ref netId)).Value))
				{
					return false;
				}
			}
			return true;
		}

		private static void RestoreHiddenOrbs()
		{
			if (HiddenOrbs.Count == 0)
			{
				return;
			}
			foreach (GenericPickupController instances in InstanceTracker.GetInstancesList<GenericPickupController>())
			{
				if ((Object)(object)instances != (Object)null && (Object)(object)instances.pickupDisplay != (Object)null && HiddenOrbs.Contains(((Object)instances).GetInstanceID()))
				{
					ApplyOrbVisibility(instances, visible: true);
				}
			}
			HiddenOrbs.Clear();
		}

		internal static void MarkCubeSyncDirty()
		{
			_cubeSyncDirty = true;
		}

		public void FixedUpdate()
		{
			if (Time.time >= _nextOrbVisibilitySweep)
			{
				_nextOrbVisibilitySweep = Time.time + 0.5f;
				RefreshOrbVisibility();
			}
			if (!_cubeSyncDirty)
			{
				return;
			}
			_cubeSyncDirty = false;
			if (!NetworkServer.active)
			{
				return;
			}
			PickupPickerController[] array = Object.FindObjectsOfType<PickupPickerController>();
			foreach (PickupPickerController val in array)
			{
				if ((Object)(object)val != (Object)null && Choices.TryGetValue(((Object)val).GetInstanceID(), out var value))
				{
					BroadcastCubeState(val, value);
				}
			}
			foreach (GenericPickupController instances in InstanceTracker.GetInstancesList<GenericPickupController>())
			{
				if ((Object)(object)instances != (Object)null && Claims.TryGetValue(((Object)instances).GetInstanceID(), out var value2))
				{
					BroadcastOrbState(instances, value2);
				}
			}
		}

		private static void OnPickerInteractionBegin(orig_OnInteractionBegin orig, PickupPickerController self, Interactor activator)
		{
			if (!HasAlreadyPicked(self, activator))
			{
				orig.Invoke(self, activator);
			}
		}

		private static Interactability OnPickerInteractability(orig_GetInteractability orig, PickupPickerController self, Interactor activator)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (HasAlreadyPicked(self, activator))
			{
				return (Interactability)0;
			}
			return orig.Invoke(self, activator);
		}

		private static bool CommandTakeoverActive(PickupPickerController picker)
		{
			if (_mode.Value == PickupMode.Individual && _shareCommandPicks.Value)
			{
				return PickupClassifier.IsCommandCube(picker);
			}
			return false;
		}

		private static bool HasAlreadyPicked(PickupPickerController picker, Interactor activator)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)activator == (Object)null)
			{
				return false;
			}
			CharacterBody component = ((Component)activator).GetComponent<CharacterBody>();
			CharacterMaster val = (((Object)(object)component != (Object)null) ? component.master : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if (!NetworkServer.active)
			{
				PickRecord cubes = ClientPickMirror.Cubes;
				NetworkInstanceId netId = ((NetworkBehaviour)picker).netId;
				uint value = ((NetworkInstanceId)(ref netId)).Value;
				netId = ((NetworkBehaviour)val).netId;
				return cubes.Contains(value, ((NetworkInstanceId)(ref netId)).Value);
			}
			if (!CommandTakeoverActive(picker))
			{
				return false;
			}
			if (Choices.TryGetValue(((Object)picker).GetInstanceID(), out var value2))
			{
				return value2.Contains(val);
			}
			return false;
		}

		private static void OnPing(orig_CmdPing orig, PingerController self, PingInfo pingInfo)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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)
			orig.Invoke(self, pingInfo);
			if (!NetworkServer.active || !_pingShowsPending.Value || _mode.Value != PickupMode.Individual || !pingInfo.active || (Object)(object)pingInfo.targetNetworkIdentity == (Object)null)
			{
				return;
			}
			GameObject gameObject = ((Component)pingInfo.targetNetworkIdentity).gameObject;
			if ((Object)(object)gameObject == (Object)null)
			{
				return;
			}
			GenericPickupController component = gameObject.GetComponent<GenericPickupController>();
			if ((Object)(object)component != (Object)null && Claims.TryGetValue(((Object)component).GetInstanceID(), out var value))
			{
				AnnouncePending(value, "still to collect");
				return;
			}
			PickupPickerController component2 = gameObject.GetComponent<PickupPickerController>();
			if ((Object)(object)component2 != (Object)null && Choices.TryGetValue(((Object)component2).GetInstanceID(), out var value2))
			{
				AnnouncePending(value2, "still to pick");
			}
		}

		private static void AnnouncePending(HashSet<CharacterMaster> done, string label)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			Collectors(Buffer);
			string text = null;
			foreach (CharacterMaster item in Buffer)
			{
				if (!done.Contains(item))
				{
					string bestMasterName = Util.GetBestMasterName(item);
					text = ((text == null) ? bestMasterName : (text + ", " + bestMasterName));
				}
			}
			if (text != null)
			{
				SimpleChatMessage val = new SimpleChatMessage();
				val.baseToken = "<style=cIsUtility>[ItemShare] {0}: {1}</style>";
				val.paramTokens = new string[2] { label, text };
				Chat.SendBroadcastChat((ChatMessageBase)(object)val);
			}
		}

		private static void Collectors(List<CharacterMaster> into)
		{
			into.Clear();
			foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances)
			{
				CharacterMaster val = (((Object)(object)instance != (Object)null) ? instance.master : null);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.inventory == (Object)null) && !IsDown(val))
				{
					into.Add(val);
				}
			}
		}

		private static void Announce(CharacterMaster picker, HashSet<CharacterMaster> claimed, List<CharacterMaster> collectors)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			if (!_announce.Value)
			{
				return;
			}
			int num = 0;
			foreach (CharacterMaster collector in collectors)
			{
				if (claimed.Contains(collector))
				{
					num++;
				}
			}
			SimpleChatMessage val = new SimpleChatMessage();
			val.baseToken = "<style=cIsUtility>[ItemShare] {0} - {1}/{2}</style>";
			val.paramTokens = new string[3]
			{
				Util.GetBestMasterName(picker),
				num.ToString(),
				collectors.Count.ToString()
			};
			Chat.SendBroadcastChat((ChatMessageBase)(object)val);
		}

		private static bool GiveDirect(Inventory inventory, PickupDef def, UniquePickup pickup)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Invalid comparison between Unknown and I4
			//IL_0028: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			if ((int)def.itemIndex != -1)
			{
				if (((UniquePickup)(ref pickup)).isTempItem)
				{
					inventory.GiveItemTemp(def.itemIndex, pickup.decayValue);
				}
				else
				{
					inventory.GiveItemPermanent(def.itemIndex, 1);
				}
				return true;
			}
			if ((int)def.equipmentIndex != -1)
			{
				if (inventory.EquipmentSetFull())
				{
					return false;
				}
				inventory.SetEquipmentIndex(def.equipmentIndex, false);
				return true;
			}
			return false;
		}

		private static bool IsShareable(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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_002e: 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)
			if ((int)def.equipmentIndex != -1)
			{
				if (_mode.Value == PickupMode.Instant)
				{
					return _shareEquipment.Value;
				}
				return false;
			}
			if ((int)def.itemIndex == -1)
			{
				return false;
			}
			ItemDef itemDef = ItemCatalog.GetItemDef(def.itemIndex);
			if ((Object)(object)itemDef != (Object)null)
			{
				return IsShareableTier(itemDef.tier);
			}
			return false;
		}

		private static bool IsShareableTier(ItemTier tier)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected I4, but got Unknown
			switch ((int)tier)
			{
			case 0:
				return _shareTier1.Value;
			case 1:
				return _shareTier2.Value;
			case 2:
				return _shareTier3.Value;
			case 4:
				return _shareBoss.Value;
			case 3:
				return _shareLunar.Value;
			case 10:
				return _shareFood.Value;
			case 6:
			case 7:
			case 8:
			case 9:
				return _shareVoid.Value;
			default:
				return false;
			}
		}

		private static bool IsDown(CharacterMaster master)
		{
			return master.IsDeadAndOutOfLivesServer();
		}
	}
	internal sealed class ItemShareStateProvider : IPickupStateProvider
	{
		public string Name => "ItemShare 1.7.1";

		public bool HasOrbState(int instanceId)
		{
			if (!ItemSharePlugin.Claims.ContainsKey(instanceId))
			{
				return ItemSharePlugin.Distributed.Contains(instanceId);
			}
			return true;
		}

		public bool HasPickerState(int instanceId)
		{
			return ItemSharePlugin.Choices.ContainsKey(instanceId);
		}

		public bool TransferOrbState(int oldInstanceId, int newInstanceId)
		{
			if (oldInstanceId == newInstanceId)
			{
				return false;
			}
			bool flag = false;
			if (ItemSharePlugin.Claims.TryGetValue(oldInstanceId, out var value))
			{
				ItemSharePlugin.Claims.Remove(oldInstanceId);
				ItemSharePlugin.Claims[newInstanceId] = value;
				flag = true;
			}
			else
			{
				ItemSharePlugin.Claims.Remove(newInstanceId);
			}
			if (flag)
			{
				ItemSharePlugin.MarkCubeSyncDirty();
			}
			if (ItemSharePlugin.Distributed.Remove(oldInstanceId))
			{
				ItemSharePlugin.Distributed.Add(newInstanceId);
				flag = true;
			}
			else
			{
				ItemSharePlugin.Distributed.Remove(newInstanceId);
			}
			return flag;
		}

		public bool TransferPickerState(int oldInstanceId, int newInstanceId)
		{
			if (oldInstanceId == newInstanceId)
			{
				return false;
			}
			if (ItemSharePlugin.Choices.TryGetValue(oldInstanceId, out var value))
			{
				ItemSharePlugin.Choices.Remove(oldInstanceId);
				ItemSharePlugin.Choices[newInstanceId] = value;
				ItemSharePlugin.MarkCubeSyncDirty();
				return true;
			}
			ItemSharePlugin.Choices.Remove(newInstanceId);
			return false;
		}

		public void ForgetOrb(int instanceId)
		{
			ItemSharePlugin.Claims.Remove(instanceId);
			ItemSharePlugin.Distributed.Remove(instanceId);
		}

		public void ForgetPicker(int instanceId)
		{
			ItemSharePlugin.Choices.Remove(instanceId);
		}
	}
}