Decompiled source of GetMeBack v1.0.0

BepInEx/plugins/GetMeBack.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("CompanyDeskTakeBack")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CompanyDeskTakeBack")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4c4f4b65-4a06-47ee-8ec1-7f1d603b42da")]
[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 CompanyDeskTakeBackMod;

[BepInPlugin("maxteam.getmeback", "GetMeBack", "1.3.3")]
public class CompanyDeskTakeBackPlugin : BaseUnityPlugin
{
	public const string Guid = "maxteam.getmeback";

	public const string Name = "GetMeBack";

	public const string Version = "1.3.3";

	internal static ManualLogSource Log;

	private void Awake()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		new Harmony("maxteam.getmeback").PatchAll();
		Log.LogInfo((object)"GetMeBack loaded successfully. DepositItemsDesk take-back is active.");
	}
}
internal static class DeskTakeBackRuntime
{
	internal sealed class State
	{
		public GrabbableObject Loot;

		public DepositItemsDesk Desk;

		public int LastAnnouncedLootId = -1;
	}

	private static readonly Dictionary<int, State> States = new Dictionary<int, State>(8);

	internal static State Get(PlayerControllerB p)
	{
		if ((Object)(object)p == (Object)null)
		{
			return null;
		}
		int instanceID = ((Object)p).GetInstanceID();
		if (!States.TryGetValue(instanceID, out var value) || value == null)
		{
			value = new State();
			States[instanceID] = value;
		}
		return value;
	}

	internal static bool TryGet(PlayerControllerB p, out State state)
	{
		state = null;
		if ((Object)(object)p == (Object)null)
		{
			return false;
		}
		if (States.TryGetValue(((Object)p).GetInstanceID(), out state))
		{
			return state != null;
		}
		return false;
	}

	internal static void Clear(PlayerControllerB p)
	{
		if ((Object)(object)p != (Object)null)
		{
			States.Remove(((Object)p).GetInstanceID());
		}
	}
}
internal static class DeskTakeBackUtil
{
	private static readonly FieldInfo CursorTipField = AccessTools.Field(typeof(PlayerControllerB), "cursorTip");

	private static readonly FieldInfo CursorIconField = AccessTools.Field(typeof(PlayerControllerB), "cursorIcon");

	private static readonly FieldInfo GrabItemIconField = AccessTools.Field(typeof(PlayerControllerB), "grabItemIcon");

	private static readonly FieldInfo GrabDistanceField = AccessTools.Field(typeof(PlayerControllerB), "grabDistance");

	private static readonly FieldInfo GrabObjectCoroutineField = AccessTools.Field(typeof(PlayerControllerB), "grabObjectCoroutine");

	private static readonly FieldInfo CurrentlyGrabbingObjectField = AccessTools.Field(typeof(PlayerControllerB), "currentlyGrabbingObject");

	private static readonly FieldInfo ThrowingObjectField = AccessTools.Field(typeof(PlayerControllerB), "throwingObject");

	private static readonly MethodInfo SetSpecialGrabAnimationBoolMethod = AccessTools.Method(typeof(PlayerControllerB), "SetSpecialGrabAnimationBool", (Type[])null, (Type[])null);

	private static readonly MethodInfo GrabObjectServerRpcMethod = AccessTools.Method(typeof(PlayerControllerB), "GrabObjectServerRpc", (Type[])null, (Type[])null);

	private static readonly MethodInfo GrabObjectMethod = AccessTools.Method(typeof(PlayerControllerB), "GrabObject", (Type[])null, (Type[])null);

	internal static bool IsLocal(PlayerControllerB p)
	{
		if ((Object)(object)p != (Object)null && (Object)(object)GameNetworkManager.Instance != (Object)null)
		{
			return (Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)(object)p;
		}
		return false;
	}

	internal static bool IsBusy(PlayerControllerB p)
	{
		if (!((Object)(object)p == (Object)null) && !p.isGrabbingObjectAnimation && !p.inSpecialMenu && (!((Object)(object)p.quickMenuManager != (Object)null) || !p.quickMenuManager.isMenuOpen) && !p.isTypingChat && !p.inTerminalMenu && !IsThrowingObject(p) && !p.IsInspectingItem && !((Object)(object)p.inAnimationWithEnemy != (Object)null) && !p.jetpackControls && !p.disablingJetpackControls && !((Object)(object)StartOfRound.Instance == (Object)null))
		{
			return StartOfRound.Instance.suckingPlayersOutOfShip;
		}
		return true;
	}

	private static bool IsThrowingObject(PlayerControllerB p)
	{
		bool flag = default(bool);
		int num;
		if ((Object)(object)p != (Object)null && ThrowingObjectField != null)
		{
			object value = ThrowingObjectField.GetValue(p);
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
		}
		else
		{
			num = 0;
		}
		return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
	}

	internal static bool TryFindDeskLoot(PlayerControllerB p, out DepositItemsDesk desk, out GrabbableObject loot)
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		desk = null;
		loot = null;
		if ((Object)(object)p == (Object)null || (Object)(object)p.gameplayCamera == (Object)null)
		{
			return false;
		}
		float num = ((GrabDistanceField != null) ? ((float)GrabDistanceField.GetValue(p)) : 5f);
		RaycastHit[] array = Physics.RaycastAll(((Component)p.gameplayCamera).transform.position, ((Component)p.gameplayCamera).transform.forward, num + 0.75f, -1, (QueryTriggerInteraction)2);
		if (array == null || array.Length == 0)
		{
			return false;
		}
		Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
		for (int num2 = 0; num2 < array.Length; num2++)
		{
			Collider collider = ((RaycastHit)(ref array[num2])).collider;
			if ((Object)(object)collider == (Object)null)
			{
				continue;
			}
			GrabbableObject componentInParent = ((Component)collider).GetComponentInParent<GrabbableObject>(true);
			if ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent.itemProperties == (Object)null || componentInParent.isHeld || componentInParent.isPocketed)
			{
				continue;
			}
			NetworkObject networkObject = ((NetworkBehaviour)componentInParent).NetworkObject;
			if (!((Object)(object)networkObject == (Object)null) && networkObject.IsSpawned)
			{
				DepositItemsDesk componentInParent2 = ((Component)componentInParent).GetComponentInParent<DepositItemsDesk>(true);
				if (!((Object)(object)componentInParent2 == (Object)null) && componentInParent2.itemsOnCounter != null && componentInParent2.itemsOnCounter.Contains(componentInParent))
				{
					desk = componentInParent2;
					loot = componentInParent;
					return true;
				}
			}
		}
		return false;
	}

	internal static void SetGrabTip(PlayerControllerB p)
	{
		if ((Object)(object)p == (Object)null || CursorTipField == null)
		{
			return;
		}
		object value = CursorTipField.GetValue(p);
		if (value == null)
		{
			return;
		}
		TMP_Text val = (TMP_Text)((value is TMP_Text) ? value : null);
		if (val != null)
		{
			val.text = "Grab : [E]";
		}
		else
		{
			value.GetType().GetProperty("text")?.SetValue(value, "Grab : [E]", null);
		}
		if (!(CursorIconField != null) || !(GrabItemIconField != null))
		{
			return;
		}
		object? value2 = CursorIconField.GetValue(p);
		Image val2 = (Image)((value2 is Image) ? value2 : null);
		if (val2 != null)
		{
			object? value3 = GrabItemIconField.GetValue(p);
			Sprite val3 = (Sprite)((value3 is Sprite) ? value3 : null);
			if (val3 != null)
			{
				((Behaviour)val2).enabled = true;
				val2.sprite = val3;
			}
		}
	}

	internal static void RemoveFromDesk(DepositItemsDesk desk, GrabbableObject loot)
	{
		if (!((Object)(object)desk == (Object)null) && !((Object)(object)loot == (Object)null))
		{
			bool flag = false;
			if (desk.itemsOnCounter != null)
			{
				flag = desk.itemsOnCounter.Remove(loot) || flag;
			}
			if ((Object)(object)((NetworkBehaviour)loot).NetworkObject != (Object)null && desk.itemsOnCounterNetworkObjects != null)
			{
				flag = desk.itemsOnCounterNetworkObjects.Remove(((NetworkBehaviour)loot).NetworkObject) || flag;
			}
			if (flag)
			{
				desk.itemsOnCounterAmount = Mathf.Max(0, desk.itemsOnCounterAmount - 1);
			}
		}
	}

	internal static bool TryStartDeskGrab(PlayerControllerB p, GrabbableObject loot)
	{
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)p == (Object)null || (Object)(object)loot == (Object)null || (Object)(object)loot.itemProperties == (Object)null)
		{
			return false;
		}
		if (loot.isHeld || loot.isPocketed)
		{
			return false;
		}
		NetworkObject networkObject = ((NetworkBehaviour)loot).NetworkObject;
		if ((Object)(object)networkObject == (Object)null || !networkObject.IsSpawned)
		{
			return false;
		}
		if (!GameNetworkManager.Instance.gameHasStarted && !loot.itemProperties.canBeGrabbedBeforeGameStart && (Object)(object)StartOfRound.Instance != (Object)null && (Object)(object)StartOfRound.Instance.testRoom == (Object)null)
		{
			return false;
		}
		try
		{
			loot.grabbable = true;
			loot.isHeld = false;
			loot.isPocketed = false;
			loot.hasHitGround = true;
			loot.EnablePhysics(true);
			CurrentlyGrabbingObjectField?.SetValue(p, loot);
			p.playerBodyAnimator.SetBool("GrabInvalidated", false);
			p.playerBodyAnimator.SetBool("GrabValidated", false);
			p.playerBodyAnimator.SetBool("cancelHolding", false);
			p.playerBodyAnimator.ResetTrigger("Throw");
			if (SetSpecialGrabAnimationBoolMethod != null)
			{
				SetSpecialGrabAnimationBoolMethod.Invoke(p, new object[2] { true, loot });
			}
			else
			{
				p.playerBodyAnimator.SetBool("Grab", true);
			}
			p.isGrabbingObjectAnimation = true;
			object? obj = CursorIconField?.GetValue(p);
			Image val = (Image)((obj is Image) ? obj : null);
			if (val != null)
			{
				((Behaviour)val).enabled = false;
			}
			object? obj2 = CursorTipField?.GetValue(p);
			TMP_Text val2 = (TMP_Text)((obj2 is TMP_Text) ? obj2 : null);
			if (val2 != null)
			{
				val2.text = string.Empty;
			}
			p.twoHanded = loot.itemProperties.twoHanded;
			p.carryWeight = Mathf.Clamp(p.carryWeight + (loot.itemProperties.weight - 1f), 1f, 10f);
			StartOfRound instance = StartOfRound.Instance;
			if (instance != null)
			{
				instance.SendChangedWeightEvent();
			}
			p.grabObjectAnimationTime = ((loot.itemProperties.grabAnimationTime > 0f) ? loot.itemProperties.grabAnimationTime : 0.4f);
			if (GrabObjectServerRpcMethod != null)
			{
				GrabObjectServerRpcMethod.Invoke(p, new object[1] { (object)new NetworkObjectReference(networkObject) });
			}
			if (GrabObjectCoroutineField != null)
			{
				object? value = GrabObjectCoroutineField.GetValue(p);
				Coroutine val3 = (Coroutine)((value is Coroutine) ? value : null);
				if (val3 != null && val3 != null)
				{
					((MonoBehaviour)p).StopCoroutine(val3);
				}
			}
			if (GrabObjectMethod != null && GrabObjectMethod.Invoke(p, null) is IEnumerator enumerator)
			{
				Coroutine value2 = ((MonoBehaviour)p).StartCoroutine(enumerator);
				GrabObjectCoroutineField?.SetValue(p, value2);
			}
			return true;
		}
		catch (Exception ex)
		{
			ManualLogSource log = CompanyDeskTakeBackPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("Desk grab start failed: " + ex.Message));
			}
			return false;
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "SetHoverTipAndCurrentInteractTrigger")]
internal static class DeskHoverPatch
{
	[HarmonyPrefix]
	private static bool Prefix(PlayerControllerB __instance)
	{
		try
		{
			if (!DeskTakeBackUtil.IsLocal(__instance))
			{
				return true;
			}
			if (DeskTakeBackUtil.IsBusy(__instance))
			{
				DeskTakeBackRuntime.Clear(__instance);
				return true;
			}
			if (!DeskTakeBackUtil.TryFindDeskLoot(__instance, out var desk, out var loot))
			{
				DeskTakeBackRuntime.Clear(__instance);
				return true;
			}
			DeskTakeBackRuntime.State state = DeskTakeBackRuntime.Get(__instance);
			state.Loot = loot;
			state.Desk = desk;
			if (state.LastAnnouncedLootId != ((Object)loot).GetInstanceID())
			{
				state.LastAnnouncedLootId = ((Object)loot).GetInstanceID();
				DeskTakeBackUtil.SetGrabTip(__instance);
			}
			return false;
		}
		catch (Exception ex)
		{
			ManualLogSource log = CompanyDeskTakeBackPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("Hover patch failed: " + ex.Message));
			}
			return true;
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "Interact_performed")]
internal static class DeskInteractPatch
{
	[HarmonyPrefix]
	private static bool Prefix(PlayerControllerB __instance, CallbackContext context)
	{
		try
		{
			if ((Object)(object)__instance == (Object)null || !((CallbackContext)(ref context)).performed)
			{
				return true;
			}
			if (!DeskTakeBackUtil.IsLocal(__instance))
			{
				return true;
			}
			if (DeskTakeBackUtil.IsBusy(__instance))
			{
				return true;
			}
			if (!DeskTakeBackRuntime.TryGet(__instance, out var state) || (Object)(object)state.Loot == (Object)null || (Object)(object)state.Desk == (Object)null)
			{
				return true;
			}
			return !DeskTakeBackUtil.TryStartDeskGrab(__instance, state.Loot);
		}
		catch (Exception ex)
		{
			ManualLogSource log = CompanyDeskTakeBackPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("Interact patch failed: " + ex.Message));
			}
			return true;
		}
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "GrabObjectClientRpc")]
internal static class DeskGrabClientRpcPatch
{
	[HarmonyPostfix]
	private static void Postfix(PlayerControllerB __instance, bool grabValidated, NetworkObjectReference grabbedObject)
	{
		try
		{
			if ((Object)(object)__instance == (Object)null || !grabValidated)
			{
				return;
			}
			GrabbableObject val = null;
			DepositItemsDesk val2 = null;
			if (DeskTakeBackRuntime.TryGet(__instance, out var state))
			{
				val = state.Loot;
				val2 = state.Desk;
			}
			NetworkObject val3 = default(NetworkObject);
			if (((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) && ((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val3, (NetworkManager)null) && (Object)(object)val3 != (Object)null)
			{
				val = ((Component)val3).GetComponentInChildren<GrabbableObject>(true);
				if ((Object)(object)val != (Object)null)
				{
					val2 = ((Component)val).GetComponentInParent<DepositItemsDesk>(true);
				}
			}
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
			{
				DeskTakeBackUtil.RemoveFromDesk(val2, val);
				DeskTakeBackRuntime.Clear(__instance);
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log = CompanyDeskTakeBackPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("Client RPC desk sync failed: " + ex.Message));
			}
		}
	}
}
[HarmonyPatch(typeof(DepositItemsDesk), "SellItemsOnServer")]
internal static class DeskSellPatch
{
	[HarmonyPrefix]
	private static void Prefix(DepositItemsDesk __instance)
	{
		try
		{
			if ((Object)(object)__instance == (Object)null || (!((NetworkBehaviour)__instance).IsServer && !((NetworkBehaviour)__instance).IsHost) || __instance.itemsOnCounter == null)
			{
				return;
			}
			for (int num = __instance.itemsOnCounter.Count - 1; num >= 0; num--)
			{
				GrabbableObject val = __instance.itemsOnCounter[num];
				if ((Object)(object)val == (Object)null || val.isHeld || val.isPocketed || (Object)(object)val.playerHeldBy != (Object)null || val.heldByPlayerOnServer)
				{
					DeskTakeBackUtil.RemoveFromDesk(__instance, val);
				}
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log = CompanyDeskTakeBackPlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)("Desk sell cleanup failed: " + ex.Message));
			}
		}
	}
}