Decompiled source of BackpackStoreNearby v1.0.0

BackpackStoreNearby.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("BackpackStoreNearby")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BackpackStoreNearby")]
[assembly: AssemblyTitle("BackpackStoreNearby")]
[assembly: AssemblyVersion("1.0.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 BackpackStoreNearby
{
	[BepInPlugin("pieter.valheim.backpackstorenearby", "Backpack Store Nearby", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "pieter.valheim.backpackstorenearby";

		public const string Name = "Backpack Store Nearby";

		public const string Version = "1.0.0";

		private const string LcfspGuid = "LuminairPrime.valheim.localcraftfromstorageprime";

		private const string AdventureBackpacksGuid = "vapok.mods.adventurebackpacks";

		private const BindingFlags Any = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static ManualLogSource _log;

		private static Plugin _instance;

		private static FieldInfo _backpackIsOpen;

		private static FieldInfo _depositButton;

		private static MethodInfo _refreshAvailability;

		private static MethodInfo _refreshOperationState;

		private static PropertyInfo _busy;

		private static MethodInfo _start;

		private static Type _depositOperation;

		private static FieldInfo _source;

		private static FieldInfo _policy;

		private static FieldInfo _identities;

		private static MethodInfo _decide;

		private static PropertyInfo _settings;

		private static PropertyInfo _settingsEnabled;

		private static PropertyInfo _settingsDepositEnabled;

		private static readonly ConditionalWeakTable<object, object> BackpackOperations = new ConditionalWeakTable<object, object>();

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

		private static bool Busy => (bool)_busy.GetValue(null);

		private void Awake()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			_instance = this;
			_log = ((BaseUnityPlugin)this).Logger;
			try
			{
				Resolve();
				Patch(new Harmony("pieter.valheim.backpackstorenearby"));
				_log.LogInfo((object)"Store Nearby button enabled for open backpacks.");
			}
			catch (Exception ex)
			{
				_log.LogError((object)("Disabled, could not hook into Local Craft From Storage Prime / Adventure Backpacks: " + ex));
			}
		}

		private static void Resolve()
		{
			_backpackIsOpen = Require(AccessTools.Field(Require(AccessTools.TypeByName("AdventureBackpacks.Patches.InventoryGuiPatches")), "BackpackIsOpen"));
			Type type = Require(AccessTools.TypeByName("LocalCraftFromStoragePrime.DepositButton"));
			_depositButton = Require(AccessTools.Field(type, "_button"));
			_refreshAvailability = Require(AccessTools.Method(type, "RefreshAvailability", (Type[])null, (Type[])null));
			_refreshOperationState = Require(AccessTools.Method(type, "RefreshOperationState", (Type[])null, (Type[])null));
			Type type2 = Require(AccessTools.TypeByName("LocalCraftFromStoragePrime.ContainerAccessService"));
			_busy = Require(AccessTools.Property(type2, "Busy"));
			_start = Require(AccessTools.Method(type2, "Start", (Type[])null, (Type[])null));
			_depositOperation = Require(AccessTools.TypeByName("LocalCraftFromStoragePrime.DepositOperation"));
			_source = Require(AccessTools.Field(_depositOperation, "_source"));
			_policy = Require(AccessTools.Field(_depositOperation, "_policy"));
			_identities = Require(AccessTools.Field(_depositOperation, "_identities"));
			_decide = Require(AccessTools.Method(AccessTools.TypeByName("LocalCraftFromStoragePrime.DepositPolicy"), "Decide", (Type[])null, (Type[])null));
			_settings = Require(AccessTools.Property(Require(AccessTools.TypeByName("LocalCraftFromStoragePrime.Plugin")), "Settings"));
			Type type3 = Require(AccessTools.TypeByName("LocalCraftFromStoragePrime.RuntimeSettings"));
			_settingsEnabled = Require(AccessTools.Property(type3, "Enabled"));
			_settingsDepositEnabled = Require(AccessTools.Property(type3, "DepositEnabled"));
		}

		private static T Require<T>(T member) where T : class
		{
			if (member == null)
			{
				throw new MissingMemberException("A member of a dependency was not found (" + typeof(T).Name + ").");
			}
			return member;
		}

		private static void Patch(Harmony harmony)
		{
			Type type = AccessTools.TypeByName("LocalCraftFromStoragePrime.DepositButton");
			Type type2 = AccessTools.TypeByName("LocalCraftFromStoragePrime.DepositAction");
			harmony.Patch((MethodBase)AccessTools.Method(type, "RefreshVisibility", (Type[])null, (Type[])null), (HarmonyMethod)null, Hook("RefreshVisibilityPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(type2, "Run", (Type[])null, (Type[])null), Hook("RunPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(_depositOperation, "InvalidReason", (Type[])null, (Type[])null), (HarmonyMethod)null, Hook("InvalidReasonPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(_depositOperation, "CanUse", (Type[])null, (Type[])null), (HarmonyMethod)null, Hook("CanUsePostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(_depositOperation, "Eligible", (Type[])null, (Type[])null), (HarmonyMethod)null, Hook("EligiblePostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static HarmonyMethod Hook(string name)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return new HarmonyMethod(typeof(Plugin).GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
		}

		private static bool BackpackOpen()
		{
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)CurrentContainer(instance) != (Object)null)
			{
				return (bool)_backpackIsOpen.GetValue(null);
			}
			return false;
		}

		private static bool DepositAllowed()
		{
			object value = _settings.GetValue(null);
			if (value != null && (bool)_settingsEnabled.GetValue(value))
			{
				return (bool)_settingsDepositEnabled.GetValue(value);
			}
			return false;
		}

		private static Container CurrentContainer(InventoryGui gui)
		{
			if (!((Object)(object)gui == (Object)null))
			{
				return CurrentContainerRef.Invoke(gui);
			}
			return null;
		}

		private static void RefreshVisibilityPostfix(InventoryGui gui)
		{
			object? value = _depositButton.GetValue(null);
			Button val = (Button)((value is Button) ? value : null);
			gui = gui ?? InventoryGui.instance;
			if ((Object)(object)val == (Object)null || (Object)(object)gui == (Object)null)
			{
				return;
			}
			RectTransform component = ((Component)val).GetComponent<RectTransform>();
			if (BackpackOpen() && DepositAllowed())
			{
				if ((Object)(object)((Transform)component).parent != (Object)(object)gui.m_container)
				{
					((Transform)component).SetParent((Transform)(object)gui.m_container, false);
				}
				((Component)val).gameObject.SetActive(true);
				_refreshAvailability.Invoke(null, new object[1] { gui });
			}
			else if ((Object)(object)((Transform)component).parent != (Object)(object)gui.m_player)
			{
				((Transform)component).SetParent((Transform)(object)gui.m_player, false);
			}
		}

		private static bool RunPrefix()
		{
			if (!BackpackOpen())
			{
				return true;
			}
			if (!Busy && DepositAllowed())
			{
				((MonoBehaviour)_instance).StartCoroutine(StoreBoth());
			}
			return false;
		}

		private static IEnumerator StoreBoth()
		{
			Player player = Player.m_localPlayer;
			InventoryGui gui = InventoryGui.instance;
			if (!CanStart(player, gui))
			{
				yield break;
			}
			Start(NewOperation(player, gui, null));
			yield return null;
			while (Busy)
			{
				yield return null;
			}
			if (CanStart(player, gui) && BackpackOpen())
			{
				Inventory inventory = CurrentContainer(gui).GetInventory();
				if (inventory != null)
				{
					Start(NewOperation(player, gui, inventory));
				}
			}
		}

		private static bool CanStart(Player player, InventoryGui gui)
		{
			if ((Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer && (Object)(object)gui != (Object)null && InventoryGui.IsVisible() && !((Character)player).IsDead() && !((Character)player).IsTeleporting())
			{
				return !Busy;
			}
			return false;
		}

		private static object NewOperation(Player player, InventoryGui gui, Inventory source)
		{
			object obj = Activator.CreateInstance(_depositOperation, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new object[2] { player, gui }, null);
			if (source != null)
			{
				_source.SetValue(obj, source);
				BackpackOperations.Add(obj, null);
			}
			return obj;
		}

		private static void Start(object operation)
		{
			_start.Invoke(null, new object[1] { operation });
			_refreshOperationState.Invoke(null, null);
		}

		private static void InvalidReasonPostfix(ref string __result)
		{
			if (__result == "cancelled" && InventoryGui.IsVisible() && BackpackOpen())
			{
				__result = null;
			}
		}

		private static void CanUsePostfix(Container chest, ref bool __result)
		{
			if (__result && (Object)(object)chest != (Object)null && BackpackOpen() && (Object)(object)chest == (Object)(object)CurrentContainer(InventoryGui.instance))
			{
				__result = false;
			}
		}

		private static void EligiblePostfix(object __instance, ItemData item, ref bool __result)
		{
			if (!__result && item?.m_shared != null && item.m_gridPos.y == 0 && !item.m_equipped && !item.m_shared.m_questItem && BackpackOperations.TryGetValue(__instance, out var _))
			{
				object value2 = _policy.GetValue(__instance);
				IDictionary dictionary = _identities.GetValue(__instance) as IDictionary;
				if (value2 != null && dictionary != null && dictionary.Contains(item))
				{
					object obj = _decide.Invoke(value2, new object[3]
					{
						dictionary[item],
						false,
						null
					});
					object value3 = obj.GetType().GetField("Item1").GetValue(obj);
					__result = Convert.ToInt32(value3) == 0;
				}
			}
		}
	}
}