Decompiled source of No Swap Drop v1.0.0

plugins/NoSwapDrop.dll

Decompiled 14 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("NoSwapDrop")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("No Swap Drop")]
[assembly: AssemblyTitle("NoSwapDrop")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 NoSwapDrop
{
	[BepInPlugin("tomo.repo.noswapdrop", "No Swap Drop", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "tomo.repo.noswapdrop";

		public const string PluginName = "No Swap Drop";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> ModEnabled;

		internal static ConfigEntry<bool> PreferOriginalSlot;

		internal static ConfigEntry<float> MaxSwapDelay;

		private void Awake()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "インベントリのスロットを切り替えたとき、手に持っているアイテムを落とさず空きスロットへ戻す。");
			PreferOriginalSlot = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PreferOriginalSlot", true, "元々入っていたスロットが空いていればそこへ戻す。false の場合は常に一番若い空きスロットへ戻す。");
			MaxSwapDelay = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaxSwapDelay", 1f, new ConfigDescription("高速で切り替えたとき、手持ちアイテムが収納可能になるまで取り出しを待つ最大秒数。これを過ぎたらバニラの挙動(落とす)に戻す。0 にすると待たない。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
			GameObject val = new GameObject("No Swap Drop SwapGuard")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			SwapGuard.Instance = val.AddComponent<SwapGuard>();
			new Harmony("tomo.repo.noswapdrop").PatchAll();
			Log.LogInfo((object)"No Swap Drop 1.0.0 loaded.");
		}
	}
	internal static class SwapTools
	{
		internal static ItemEquippable GetItemInHand()
		{
			PhysGrabber instance = PhysGrabber.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			PhysGrabObject val = null;
			if (instance.grabbed && (Object)(object)instance.grabbedPhysGrabObject != (Object)null)
			{
				val = instance.grabbedPhysGrabObject;
			}
			else if ((Object)(object)instance.overrideGrabTarget != (Object)null)
			{
				val = instance.overrideGrabTarget;
			}
			if (!((Object)(object)val == (Object)null))
			{
				return ((Component)val).GetComponent<ItemEquippable>();
			}
			return null;
		}

		internal static bool CanStow(ItemEquippable item)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			Inventory instance = Inventory.instance;
			if ((Object)(object)item != (Object)null && (Object)(object)instance != (Object)null && instance.spotsFeched && (int)item.currentState == 0 && !item.isEquipping && !item.isUnequipping && !instance.IsItemEquipped(item))
			{
				return FindSpot(item) >= 0;
			}
			return false;
		}

		internal static bool IsSettling(ItemEquippable item)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			if ((Object)(object)item != (Object)null)
			{
				if ((int)item.currentState != 3 && (int)item.currentState != 1 && !item.isEquipping)
				{
					return item.isUnequipping;
				}
				return true;
			}
			return false;
		}

		internal static bool HasFreeSpot(ItemEquippable item)
		{
			return FindSpot(item) >= 0;
		}

		internal static bool Stow(ItemEquippable item)
		{
			PhysGrabber instance = PhysGrabber.instance;
			int num = FindSpot(item);
			if ((Object)(object)instance == (Object)null || num < 0)
			{
				return false;
			}
			item.RequestEquip(num, instance.photonView.ViewID);
			Plugin.Log.LogDebug((object)("Stowing held item into inventory spot " + num + "."));
			return true;
		}

		internal static bool IsStowed(ItemEquippable item)
		{
			Inventory instance = Inventory.instance;
			if (!((Object)(object)item == (Object)null))
			{
				if ((Object)(object)instance != (Object)null)
				{
					return instance.IsItemEquipped(item);
				}
				return false;
			}
			return true;
		}

		private static int FindSpot(ItemEquippable item)
		{
			Inventory instance = Inventory.instance;
			if ((Object)(object)instance == (Object)null || !instance.spotsFeched)
			{
				return -1;
			}
			List<InventorySpot> allSpots = instance.GetAllSpots();
			if (Plugin.PreferOriginalSlot.Value)
			{
				int inventorySpotIndex = item.inventorySpotIndex;
				if (inventorySpotIndex >= 0 && inventorySpotIndex < allSpots.Count && (Object)(object)allSpots[inventorySpotIndex] != (Object)null && !allSpots[inventorySpotIndex].IsOccupied())
				{
					return inventorySpotIndex;
				}
			}
			for (int i = 0; i < allSpots.Count; i++)
			{
				if ((Object)(object)allSpots[i] != (Object)null && !allSpots[i].IsOccupied())
				{
					return i;
				}
			}
			return -1;
		}
	}
	internal class SwapGuard : MonoBehaviour
	{
		internal static SwapGuard Instance;

		internal static bool Bypass;

		private ItemEquippable pendingTake;

		private ItemEquippable stowing;

		private bool waitingForStow;

		private float deadline;

		internal void Defer(ItemEquippable itemToTakeOut)
		{
			pendingTake = itemToTakeOut;
			stowing = null;
			waitingForStow = false;
			deadline = Time.time + Plugin.MaxSwapDelay.Value;
		}

		private void Clear()
		{
			pendingTake = null;
			stowing = null;
			waitingForStow = false;
		}

		private void Update()
		{
			if ((Object)(object)pendingTake == (Object)null)
			{
				return;
			}
			if (!pendingTake.IsEquipped())
			{
				Clear();
				return;
			}
			if (Time.time >= deadline)
			{
				TakeOutNow();
				return;
			}
			if (waitingForStow)
			{
				if (SwapTools.IsStowed(stowing))
				{
					TakeOutNow();
				}
				return;
			}
			ItemEquippable itemInHand = SwapTools.GetItemInHand();
			if ((Object)(object)itemInHand == (Object)null || (Object)(object)itemInHand == (Object)(object)pendingTake)
			{
				TakeOutNow();
			}
			else if (SwapTools.CanStow(itemInHand))
			{
				if (SwapTools.Stow(itemInHand))
				{
					stowing = itemInHand;
					waitingForStow = true;
				}
				else
				{
					TakeOutNow();
				}
			}
		}

		private void TakeOutNow()
		{
			ItemEquippable val = pendingTake;
			Clear();
			if ((Object)(object)val == (Object)null || !val.IsEquipped())
			{
				return;
			}
			Bypass = true;
			try
			{
				val.RequestUnequip();
			}
			finally
			{
				Bypass = false;
			}
		}
	}
	[HarmonyPatch(typeof(ItemEquippable), "RequestUnequip")]
	internal static class RequestUnequipPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(ItemEquippable __instance)
		{
			try
			{
				return Handle(__instance);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("No Swap Drop failed, falling back to vanilla behaviour: " + ex));
				return true;
			}
		}

		private static bool Handle(ItemEquippable itemBeingTakenOut)
		{
			if (SwapGuard.Bypass || !Plugin.ModEnabled.Value)
			{
				return true;
			}
			if ((Object)(object)itemBeingTakenOut == (Object)null || !itemBeingTakenOut.IsEquipped())
			{
				return true;
			}
			Inventory instance = Inventory.instance;
			if ((Object)(object)instance == (Object)null || !instance.spotsFeched)
			{
				return true;
			}
			ItemEquippable itemInHand = SwapTools.GetItemInHand();
			if ((Object)(object)itemInHand == (Object)null || (Object)(object)itemInHand == (Object)(object)itemBeingTakenOut)
			{
				return true;
			}
			if (!SwapTools.HasFreeSpot(itemInHand))
			{
				return true;
			}
			if (SwapTools.CanStow(itemInHand))
			{
				SwapTools.Stow(itemInHand);
				return true;
			}
			if (SwapTools.IsSettling(itemInHand) && Plugin.MaxSwapDelay.Value > 0f && (Object)(object)SwapGuard.Instance != (Object)null)
			{
				SwapGuard.Instance.Defer(itemBeingTakenOut);
				return false;
			}
			return true;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}