Decompiled source of ItemShare v1.3.0

ItemShare.dll

Decompiled 19 hours 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 Microsoft.CodeAnalysis;
using On.RoR2;
using RoR2;
using UnityEngine;
using UnityEngine.Events;
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.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0")]
[assembly: AssemblyProduct("ItemShare")]
[assembly: AssemblyTitle("ItemShare")]
[assembly: AssemblyVersion("1.3.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ItemShare
{
	public enum PickupMode
	{
		Instant,
		Individual
	}
	[BepInPlugin("com.majai.itemshare", "ItemShare", "1.3.0")]
	public class ItemSharePlugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_AttemptGrant <0>__OnAttemptGrant;

			public static hook_HandlePickupSelected <1>__OnPickupSelected;

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

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

		public const string Name = "ItemShare";

		public const string Version = "1.3.0";

		internal static ManualLogSource Log;

		private static ConfigEntry<PickupMode> _mode;

		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 readonly HashSet<int> Distributed = new HashSet<int>();

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

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

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

		public void Awake()
		{
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Expected O, but got Unknown
			//IL_01bb: 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_01c6: 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.");
			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;
			Stage.onStageStartGlobal += OnStageStart;
			Log.LogInfo((object)string.Format("{0} {1} loaded in {2} mode.", "ItemShare", "1.3.0", _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
			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;
			Stage.onStageStartGlobal -= OnStageStart;
		}

		private static void OnStageStart(Stage stage)
		{
			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_0149: 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);
			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_0058: 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)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_010d: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || _mode.Value != PickupMode.Individual || !_shareCommandPicks.Value || !IsPickupSpawningPicker(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);
			}
			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 static bool IsPickupSpawningPicker(PickupPickerController picker)
		{
			if (picker.isDelusionChoice || picker.isRebirthChoice)
			{
				return false;
			}
			if (!HasCreatePickupListener((UnityEventBase)(object)picker.onPickupSelected))
			{
				return HasCreatePickupListener((UnityEventBase)(object)picker.onUniquePickupSelected);
			}
			return true;
		}

		private static bool HasCreatePickupListener(UnityEventBase choiceEvent)
		{
			if (choiceEvent == null)
			{
				return false;
			}
			int persistentEventCount = choiceEvent.GetPersistentEventCount();
			for (int i = 0; i < persistentEventCount; i++)
			{
				if (choiceEvent.GetPersistentMethodName(i) == "CreatePickup")
				{
					return true;
				}
			}
			return false;
		}

		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();
		}
	}
}