Decompiled source of BulkPickupMod v1.3.0

BepInEx/plugins/BulkPickupMod/BulkPickupMod.dll

Decompiled 2 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 FishNet.Object;
using HarmonyLib;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[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("BulkPickupMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BulkPickupMod")]
[assembly: AssemblyTitle("BulkPickupMod")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BulkPickupMod;

[BepInPlugin("com.bulkpickup.htf", "BulkPickupMod", "1.3.0")]
[BepInProcess("How to Fish")]
public class BulkPickupMod : BaseUnityPlugin
{
	[HarmonyPatch(typeof(BossManager), "SpawnBossTrophy")]
	private static class BossTrophyPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			_taggingBossDrops = true;
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			_taggingBossDrops = false;
		}
	}

	[HarmonyPatch(typeof(ItemManager), "Add", new Type[]
	{
		typeof(Item),
		typeof(Collider),
		typeof(Collider[])
	})]
	private static class ItemAddPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Item item)
		{
			if (_taggingBossDrops && (Object)(object)item != (Object)null)
			{
				_bossDropItems.Add(item);
			}
		}
	}

	[HarmonyPatch(typeof(AudioManager), "PlayPlayerClip")]
	private static class AudioPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(string clip, Player player, bool variation, AudioDistance distance, float volume, float minDelay)
		{
			if (_playOneSound && _bulkItems.Count > 0 && clip == "PickUp")
			{
				return false;
			}
			return true;
		}
	}

	public const string PluginGuid = "com.bulkpickup.htf";

	public const string PluginName = "BulkPickupMod";

	public const string PluginVersion = "1.3.0";

	public static ConfigEntry<float> PickupRadius;

	public static ConfigEntry<string> PickupModifier;

	public static ConfigEntry<bool> AutoPickupEnabled;

	public static ConfigEntry<float> AutoPickupInterval;

	public static ConfigEntry<bool> IgnoreFullInventory;

	public static ConfigEntry<bool> PlayPickupSoundOnce;

	public static ConfigEntry<bool> PickupFish;

	public static ConfigEntry<bool> PickupWeapons;

	public static ConfigEntry<bool> PickupCreatures;

	public static ConfigEntry<bool> PickupItems;

	public static ConfigEntry<bool> PickupBossDrops;

	private static readonly HashSet<Item> _bulkItems = new HashSet<Item>();

	private static readonly HashSet<Item> _bossDropItems = new HashSet<Item>();

	private static bool _taggingBossDrops;

	private static bool _playOneSound;

	private float _nextAutoScan;

	private void Awake()
	{
		PickupRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "PickupRadius", 5f, "World scan radius in Unity meters.");
		PickupModifier = ((BaseUnityPlugin)this).Config.Bind<string>("General", "PickupModifier", "LeftShift", "Modifier key for bulk pickup. Options: LeftShift, RightShift, None.");
		AutoPickupEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Auto", "AutoPickupEnabled", false, "Automatically bulk-pickup everything in radius every AutoPickupInterval seconds (no key needed).");
		AutoPickupInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Auto", "AutoPickupInterval", 0.5f, "Time interval (seconds) between automatic scans.");
		IgnoreFullInventory = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IgnoreFullInventory", true, "Prevents scan attempts if the local inventory is completely full.");
		PlayPickupSoundOnce = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PlayPickupSoundOnce", true, "Plays one pickup sound instead of one per item.");
		PickupFish = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "PickupFish", true, "Bulk-pick up Fish-type items.");
		PickupWeapons = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "PickupWeapons", true, "Bulk-pick up Weapon-type items.");
		PickupCreatures = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "PickupCreatures", true, "Bulk-pick up non-fish Creature-type items (birds, crabs, albatross, etc.).");
		PickupItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "PickupItems", true, "Bulk-pick up all other Item-type items (tools, bait, junk, other).");
		PickupBossDrops = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "PickupBossDrops", true, "Bulk-pick up boss/mini-boss trophy and meat drops independently of other filters.");
		Harmony.CreateAndPatchAll(typeof(BulkPickupMod), "com.bulkpickup.htf");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"BulkPickupMod v1.3.0 loaded.");
	}

	private void Update()
	{
		Player localPlayer = Player.LocalPlayer;
		if (Object.op_Implicit((Object)(object)localPlayer) && !localPlayer.BlockInputs)
		{
			if (AutoPickupEnabled.Value && Time.time >= _nextAutoScan)
			{
				_nextAutoScan = Time.time + Mathf.Max(0.1f, AutoPickupInterval.Value);
				TryBulkPickup(localPlayer);
			}
			if (ModifierHeld() && PickupPressedThisFrame())
			{
				TryBulkPickup(localPlayer);
			}
		}
	}

	private bool ModifierHeld()
	{
		if (Keyboard.current == null)
		{
			return false;
		}
		string text = PickupModifier.Value.Trim().ToLower();
		if (!(text == "rightshift"))
		{
			if (text == "none")
			{
				return true;
			}
			return ((ButtonControl)Keyboard.current.leftShiftKey).isPressed;
		}
		return ((ButtonControl)Keyboard.current.rightShiftKey).isPressed;
	}

	private bool PickupPressedThisFrame()
	{
		if ((Object)(object)GameInfo.Input == (Object)null || (Object)(object)GameInfo.Input.actions == (Object)null)
		{
			return false;
		}
		InputAction val = GameInfo.Input.actions["PlayerPickUp"];
		if (val != null)
		{
			return val.WasPressedThisFrame();
		}
		return false;
	}

	private static void TryBulkPickup(Player player)
	{
		//IL_000d: 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)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: 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_0104: Invalid comparison between Unknown and I4
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Invalid comparison between Unknown and I4
		Vector3 playerPos = player.Transform.position;
		float num = PickupRadius.Value * PickupRadius.Value;
		List<Item> list = null;
		foreach (KeyValuePair<Transform, Item> item in ItemManager.Items)
		{
			Item value = item.Value;
			if (!Object.op_Implicit((Object)(object)value) || !value.CanPickUp || !value.IsInteractable || value.HasPlayerHolder || value.IsInInventory || value.IsDestroying || ((NetworkBehaviour)value).IsDeinitializing || (Object)(object)value.SyncedHolder != (Object)null)
			{
				continue;
			}
			Vector3 val = ((Component)value).transform.position - playerPos;
			if (((Vector3)(ref val)).sqrMagnitude > num)
			{
				continue;
			}
			if (!PickupBossDrops.Value || !_bossDropItems.Contains(value))
			{
				ItemType type = value.Type;
				if ((int)type != 1)
				{
					if ((int)type == 2)
					{
						if (!PickupWeapons.Value)
						{
							continue;
						}
					}
					else if ((Object)(object)value.Creature != (Object)null)
					{
						if (!PickupCreatures.Value)
						{
							continue;
						}
					}
					else if (!PickupItems.Value)
					{
						continue;
					}
				}
				else if (!PickupFish.Value)
				{
					continue;
				}
			}
			if (list == null)
			{
				list = new List<Item>();
			}
			list.Add(value);
		}
		if (list == null || (IgnoreFullInventory.Value && IsInventoryFull(player.Inventory, list)))
		{
			return;
		}
		list.Sort(delegate(Item a, Item b)
		{
			//IL_0006: 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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val2 = ((Component)a).transform.position - playerPos;
			float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
			val2 = ((Component)b).transform.position - playerPos;
			return sqrMagnitude.CompareTo(((Vector3)(ref val2)).sqrMagnitude);
		});
		bool flag = PlayPickupSoundOnce.Value && list.Count > 1;
		bool flag2 = false;
		_bulkItems.Clear();
		foreach (Item item2 in list)
		{
			_bulkItems.Add(item2);
		}
		_playOneSound = flag;
		foreach (Item item3 in list)
		{
			if (Object.op_Implicit((Object)(object)item3) && !item3.HasPlayerHolder && !item3.IsInInventory && !item3.IsDestroying && !((NetworkBehaviour)item3).IsDeinitializing)
			{
				item3.PickUp(player, true, true);
				flag2 = true;
			}
		}
		_bulkItems.Clear();
		_playOneSound = false;
		if (flag && flag2)
		{
			AudioManager.PlayPlayerClip("PickUp", player, false, (AudioDistance)0, 0.2f, 0.1f);
		}
	}

	private static bool IsInventoryFull(PlayerInventory inventory, List<Item> candidates)
	{
		if (!Object.op_Implicit((Object)(object)inventory))
		{
			return false;
		}
		try
		{
			int value = Traverse.Create((object)inventory).Method("GetTotalSlots", Array.Empty<object>()).GetValue<int>();
			IDictionary<byte, Item> value2 = Traverse.Create((object)inventory).Field("_items").GetValue<IDictionary<byte, Item>>();
			if (value <= 0)
			{
				return false;
			}
			int num = 0;
			foreach (KeyValuePair<byte, Item> item in value2)
			{
				if ((Object)(object)item.Value != (Object)null)
				{
					num++;
				}
			}
			if (num < value)
			{
				return false;
			}
			Type type = AccessTools.TypeByName("StackableItems.StackManager");
			if (type == null)
			{
				return true;
			}
			MethodInfo method = type.GetMethod("GetStackCount", BindingFlags.Static | BindingFlags.Public);
			PropertyInfo property = type.GetProperty("MaxStackSize", BindingFlags.Static | BindingFlags.Public);
			int num2 = ((property != null) ? ((int)property.GetValue(null, null)) : 64);
			foreach (Item candidate in candidates)
			{
				if (!Object.op_Implicit((Object)(object)candidate))
				{
					continue;
				}
				string text = ((Object)candidate).name.Replace("(Clone)", "").Trim();
				bool flag = false;
				foreach (KeyValuePair<byte, Item> item2 in value2)
				{
					Item value3 = item2.Value;
					if (!((Object)(object)value3 == (Object)null) && !((Object)(object)value3.Weapon != (Object)null) && ((Object)value3).name.Replace("(Clone)", "").Trim() == text)
					{
						int num3 = ((method != null) ? ((int)method.Invoke(null, new object[2] { inventory, item2.Key })) : 0);
						if (1 + num3 < num2)
						{
							flag = true;
							break;
						}
					}
				}
				if (flag)
				{
					return false;
				}
			}
			return true;
		}
		catch
		{
			return false;
		}
	}
}