Decompiled source of QuickStackStore v1.0.1

QuickStackStore.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace QuickStackStore;

[BepInPlugin("com.parallel53.quickstackstore", "QuickStackStore", "1.0.1")]
public class QuickStackStorePlugin : BaseUnityPlugin
{
	private const int HotbarRow = 0;

	private static readonly FieldRef<InventoryGui, Container> CurrentContainer = AccessTools.FieldRefAccess<InventoryGui, Container>("m_currentContainer");

	private static readonly Func<Container, long, bool> CheckAccess = AccessTools.MethodDelegate<Func<Container, long, bool>>(AccessTools.Method(typeof(Container), "CheckAccess", (Type[])null, (Type[])null), (object)null, true);

	private static readonly HashSet<Container> Requested = new HashSet<Container>();

	private static ConfigEntry<float> radius;

	private static ConfigEntry<bool> keepHotbar;

	private const float DropFraction = 0.25f;

	private static Button button;

	private static bool answeringRequest;

	private void Awake()
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected O, but got Unknown
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		radius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Radius", 10f, new ConfigDescription("How far away a chest can be, in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
		keepHotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "KeepHotbar", true, "Leave items on your hotbar where they are.");
		new Harmony("com.parallel53.quickstackstore").PatchAll(typeof(QuickStackStorePlugin));
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(InventoryGui), "Awake")]
	private static void AddButton(InventoryGui __instance)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Expected O, but got Unknown
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Expected O, but got Unknown
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//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_011e: Unknown result type (might be due to invalid IL or missing references)
		button = Object.Instantiate<Button>(__instance.m_takeAllButton, (Transform)(object)__instance.m_player);
		((Object)button).name = "QuickStackButton";
		((Selectable)button).interactable = true;
		button.onClick = new ButtonClickedEvent();
		((UnityEvent)button.onClick).AddListener(new UnityAction(OnClick));
		UIGamePad[] componentsInChildren = ((Component)button).GetComponentsInChildren<UIGamePad>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
		}
		Localize[] componentsInChildren2 = ((Component)button).GetComponentsInChildren<Localize>(true);
		for (int i = 0; i < componentsInChildren2.Length; i++)
		{
			Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
		}
		((Component)button).GetComponentInChildren<TMP_Text>(true).text = "Quick Stack";
		RectTransform val = (RectTransform)((Component)button).transform;
		val.anchorMin = new Vector2(0.5f, 0f);
		val.anchorMax = new Vector2(0.5f, 0f);
		val.pivot = new Vector2(0.5f, 0.5f);
		Rect rect = val.rect;
		val.anchoredPosition = new Vector2(0f, (0f - ((Rect)(ref rect)).height) * 0.25f);
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(InventoryGui), "Update")]
	private static void RefreshButton(InventoryGui __instance)
	{
		bool flag = (Object)(object)CurrentContainer.Invoke(__instance) == (Object)null;
		if ((Object)(object)button != (Object)null && ((Component)button).gameObject.activeSelf != flag)
		{
			((Component)button).gameObject.SetActive(flag);
		}
	}

	private static void OnClick()
	{
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			StackIntoNearbyChests(Player.m_localPlayer);
		}
	}

	private static void StackIntoNearbyChests(Player player)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = ((Component)player).transform.position;
		List<Piece> list = new List<Piece>();
		Piece.GetAllPiecesInRadius(position, radius.Value, list);
		List<ItemData> items = (from item in ((Humanoid)player).GetInventory().GetAllItems()
			where !((Humanoid)player).IsItemEquiped(item) && !StaysWithPlayer(item)
			select item).ToList();
		List<Container> list2 = (from piece in list
			select ((Component)piece).GetComponentInChildren<Container>() into chest
			where (Object)(object)chest != (Object)null && chest.GetInventory() != null
			where IsAvailable(chest, player)
			where items.Any((ItemData item) => chest.GetInventory().ContainsItemByName(item.m_shared.m_name))
			orderby Vector3.Distance(position, ((Component)chest).transform.position)
			select chest).ToList();
		if (list2.Count == 0)
		{
			((Character)player).Message((MessageType)2, "Nothing to stack nearby", 0, (Sprite)null, false);
			return;
		}
		Requested.Clear();
		foreach (Container item in list2)
		{
			Requested.Add(item);
			item.StackAll();
		}
	}

	private static bool IsAvailable(Container chest, Player player)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		if (!chest.IsInUse() && CheckAccess(chest, Game.instance.GetPlayerProfile().GetPlayerID()))
		{
			if (chest.m_checkGuardStone)
			{
				return PrivateArea.CheckAccess(((Component)chest).transform.position, 0f, false, false);
			}
			return true;
		}
		return false;
	}

	private static bool StaysWithPlayer(ItemData item)
	{
		if (item.m_shared.m_maxStackSize > 1)
		{
			if (keepHotbar.Value)
			{
				return item.m_gridPos.y == 0;
			}
			return false;
		}
		return true;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Container), "RPC_StackResponse")]
	private static void BeforeStackResponse(Container __instance)
	{
		answeringRequest = Requested.Remove(__instance);
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Container), "RPC_StackResponse")]
	private static void AfterStackResponse()
	{
		answeringRequest = false;
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Humanoid), "IsItemEquiped")]
	private static void KeepItems(ItemData item, ref bool __result)
	{
		if (answeringRequest && StaysWithPlayer(item))
		{
			__result = true;
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Inventory), "StackAll")]
	private static void SilenceChestMessage(ref bool __state, object[] __args)
	{
		__state = answeringRequest;
		if (answeringRequest)
		{
			__args[1] = false;
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Inventory), "StackAll")]
	private static void ReportStacked(bool __state, int __result)
	{
		if (__state && __result > 0)
		{
			((Character)Player.m_localPlayer).Message((MessageType)1, "Quick stacked " + __result + " items", 0, (Sprite)null, false);
		}
	}
}