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 States = new Dictionary(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(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(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(true); if ((Object)(object)val != (Object)null) { val2 = ((Component)val).GetComponentInParent(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)); } } } }