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+942e46783df06b28bd0fd341f11ad1e17599f2ba")] [assembly: AssemblyProduct("InAirItems")] [assembly: AssemblyTitle("InAirItems")] [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 InAirItems { [BepInPlugin("sbg.inairitems", "InAirItems", "0.2.2")] 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.2"; internal static ManualLogSource Log; internal static Plugin Instance; internal ConfigEntry 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("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), "k__BackingField"); new Harmony("sbg.inairitems").PatchAll(); Log.LogInfo((object)"InAirItems v0.2.2 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, false); 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); } } } } }