Decompiled source of InAirItems v0.2.1

InAirItems.dll

Decompiled 3 hours ago
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using UnityEngine;

[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("InAirItems")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("InAirItems")]
[assembly: AssemblyTitle("InAirItems")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 InAirItems
{
	[BepInPlugin("sbg.inairitems", "InAirItems", "0.2.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(PlayerInventory), "TryUseSpringBoots")]
		internal static class Patch_PlayerInventory_TryUseSpringBoots
		{
			private static void Postfix(PlayerInventory __instance, bool __result)
			{
				if (!__result || (Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).isLocalPlayer)
				{
					return;
				}
				int equippedItemIndex = __instance.EquippedItemIndex;
				int num = FindNextUsableSlot(__instance, equippedItemIndex);
				if ((Object)(object)Instance != (Object)null && Instance.verboseLoggingConfig.Value)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)$"InAirItems: boots fired (currentIndex={equippedItemIndex}); next-usable-slot={num}.");
					}
				}
				if (num >= 0 && num != equippedItemIndex && (Object)(object)Instance != (Object)null)
				{
					((MonoBehaviour)Instance).StartCoroutine(DeferredSelect(__instance, equippedItemIndex, num));
				}
			}
		}

		public const string ModGuid = "sbg.inairitems";

		public const string ModName = "InAirItems";

		public const string ModVersion = "0.2.1";

		internal static ManualLogSource Log;

		internal static Plugin Instance;

		internal ConfigEntry<bool> verboseLoggingConfig;

		private static MethodInfo getEffectiveSlotMethod;

		private static FieldInfo equippedItemIndexBackingField;

		private void Awake()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			verboseLoggingConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "VerboseLogging", false, "Emit diagnostic lines when boots fire, what next slot we tried to select, and whether vanilla TrySelectItemSlot accepted. Off by default; flip on if the auto-select still misbehaves.");
			getEffectiveSlotMethod = AccessTools.Method(typeof(PlayerInventory), "GetEffectiveSlot", (Type[])null, (Type[])null);
			equippedItemIndexBackingField = AccessTools.Field(typeof(PlayerInventory), "<EquippedItemIndex>k__BackingField");
			new Harmony("sbg.inairitems").PatchAll();
			Log.LogInfo((object)"InAirItems v0.2.1 loaded.");
		}

		private static IEnumerator DeferredSelect(PlayerInventory inventory, int bootsIndex, int nextIndex)
		{
			yield return null;
			for (int attempt = 0; attempt < 3; attempt++)
			{
				if (!((Object)(object)inventory != (Object)null))
				{
					break;
				}
				if (inventory.EquippedItemIndex != bootsIndex)
				{
					LogVerbose($"InAirItems: equipped index changed to {inventory.EquippedItemIndex} before our select; skipping.");
					yield break;
				}
				bool flag = inventory.TrySelectItemSlot(nextIndex);
				LogVerbose($"InAirItems: TrySelectItemSlot({nextIndex}) attempt {attempt + 1} -> {flag}.");
				if (flag)
				{
					yield break;
				}
				yield return null;
			}
			if ((Object)(object)inventory != (Object)null && inventory.EquippedItemIndex == bootsIndex && equippedItemIndexBackingField != null)
			{
				LogVerbose($"InAirItems: TrySelectItemSlot kept refusing; writing EquippedItemIndex = {nextIndex} directly.");
				equippedItemIndexBackingField.SetValue(inventory, nextIndex);
				PlayerInfo playerInfo = inventory.PlayerInfo;
				if (playerInfo != null)
				{
					playerInfo.SetEquippedItemIndex(nextIndex);
				}
			}
		}

		private static int FindNextUsableSlot(PlayerInventory inventory, int startIndex)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0063: Invalid comparison between Unknown and I4
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)GameManager.PlayerInventorySettings == (Object)null)
			{
				return -1;
			}
			int maxItems = GameManager.PlayerInventorySettings.MaxItems;
			if (maxItems <= 0)
			{
				return -1;
			}
			for (int i = 1; i <= maxItems; i++)
			{
				int num = (startIndex + i) % maxItems;
				if (num != startIndex)
				{
					InventorySlot val;
					try
					{
						val = (InventorySlot)getEffectiveSlotMethod.Invoke(inventory, new object[1] { num });
					}
					catch
					{
						continue;
					}
					if ((int)val.itemType != 0 && (int)val.itemType != 5 && val.remainingUses > 0)
					{
						return num;
					}
				}
			}
			return -1;
		}

		private static void LogVerbose(string message)
		{
			if ((Object)(object)Instance != (Object)null && Instance.verboseLoggingConfig.Value)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)message);
				}
			}
		}
	}
}