Decompiled source of FastSlots v1.0.2

BepInEx/plugins/FastSlots.dll

Decompiled a month ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using GameNetcodeStuff;
using HarmonyLib;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("FastSlots")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FastSlots")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a72f02b8-2b77-417b-b41a-dc8936c5b39a")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FastSlots;

[BepInPlugin("FastSlots", "FastSlots", "1.0.2")]
public class FastSlotsPlugin : BaseUnityPlugin
{
	private void Awake()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		new Harmony("FastSlots").PatchAll();
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "Update")]
public static class PlayerUpdatePatch
{
	private static readonly MethodInfo SwitchToItemSlot = AccessTools.Method(typeof(PlayerControllerB), "SwitchToItemSlot", new Type[2]
	{
		typeof(int),
		typeof(GrabbableObject)
	}, (Type[])null);

	private static readonly Key[] SlotKeys;

	[HarmonyPostfix]
	private static void Postfix(PlayerControllerB __instance)
	{
		if (IsControllable(__instance))
		{
			Keyboard current = Keyboard.current;
			if (current != null)
			{
				Traverse t = Traverse.Create((object)__instance);
				TryPlayEmote(__instance, current, t);
				TrySwitchSlot(__instance, current, t);
			}
		}
	}

	private static bool IsControllable(PlayerControllerB p)
	{
		return ((NetworkBehaviour)p).IsOwner && p.isPlayerControlled && !p.isTypingChat && !p.quickMenuManager.isMenuOpen;
	}

	private static void TryPlayEmote(PlayerControllerB p, Keyboard kb, Traverse t)
	{
		int num = (((ButtonControl)kb.downArrowKey).wasPressedThisFrame ? 1 : (((ButtonControl)kb.upArrowKey).wasPressedThisFrame ? 2 : (-1)));
		if (num != -1)
		{
			t.Method("StartPerformingEmoteServerRpc", Array.Empty<object>()).GetValue();
			p.playerBodyAnimator.SetInteger("emoteNumber", num);
		}
	}

	private static void TrySwitchSlot(PlayerControllerB p, Keyboard kb, Traverse t)
	{
		if (CanSwitchSlot(p, t))
		{
			int pressedSlot = GetPressedSlot(kb);
			if (pressedSlot != -1 && pressedSlot < p.ItemSlots.Length && pressedSlot != p.currentItemSlot)
			{
				PerformSlotSwitch(p, t, pressedSlot);
			}
		}
	}

	private static bool CanSwitchSlot(PlayerControllerB p, Traverse t)
	{
		return t.Field("timeSinceSwitchingSlots").GetValue<float>() >= 0.3f && !p.isGrabbingObjectAnimation && !p.inSpecialInteractAnimation && !p.twoHanded && !p.activatingItem && !t.Field("throwingObject").GetValue<bool>();
	}

	private static int GetPressedSlot(Keyboard kb)
	{
		for (int i = 0; i < SlotKeys.Length; i++)
		{
			if (((ButtonControl)kb[SlotKeys[i]]).wasPressedThisFrame)
			{
				return i;
			}
		}
		return -1;
	}

	private static void PerformSlotSwitch(PlayerControllerB p, Traverse t, int slot)
	{
		ShipBuildModeManager instance = ShipBuildModeManager.Instance;
		if (instance != null)
		{
			instance.CancelBuildMode(true);
		}
		p.playerBodyAnimator.SetBool("GrabValidated", false);
		SwitchToItemSlot.Invoke(p, new object[2] { slot, null });
		t.Method("SwitchToSlotServerRpc", new object[1] { slot }).GetValue();
		GrabbableObject currentlyHeldObjectServer = p.currentlyHeldObjectServer;
		if (currentlyHeldObjectServer != null)
		{
			AudioSource component = ((Component)currentlyHeldObjectServer).gameObject.GetComponent<AudioSource>();
			if (component != null)
			{
				component.PlayOneShot(currentlyHeldObjectServer.itemProperties.grabSFX, 0.6f);
			}
		}
		t.Field("timeSinceSwitchingSlots").SetValue((object)0f);
	}

	static PlayerUpdatePatch()
	{
		Key[] array = new Key[7];
		RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
		SlotKeys = (Key[])(object)array;
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "PerformEmote")]
public static class EmotePatch
{
	private static readonly Key[] BlockedKeys = (Key[])(object)new Key[2]
	{
		(Key)41,
		(Key)42
	};

	[HarmonyPrefix]
	private static bool Prefix()
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		Keyboard current = Keyboard.current;
		if (current == null)
		{
			return true;
		}
		Key[] blockedKeys = BlockedKeys;
		foreach (Key val in blockedKeys)
		{
			if (((ButtonControl)current[val]).isPressed)
			{
				return false;
			}
		}
		return true;
	}
}