Decompiled source of AntiItemTeleport v1.4.0

BepInEx/plugins/RepoAntiItemTeleport.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using AntiItemTeleport.Core;
using AntiItemTeleport.Patches;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using Steamworks;
using Steamworks.Data;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RepoAntiItemTeleport")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: AssemblyInformationalVersion("1.4.0")]
[assembly: AssemblyProduct("Anti Item Teleport")]
[assembly: AssemblyTitle("RepoAntiItemTeleport")]
[assembly: AssemblyVersion("1.4.0.0")]
namespace AntiItemTeleport
{
	[BepInPlugin("com.sunwu.anti_Item_teleport", "Anti Item Teleport", "1.4.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal const string Guid = "com.sunwu.anti_Item_teleport";

		internal const string Name = "Anti Item Teleport";

		internal const string Version = "1.4.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> AutoKick;

		internal static ConfigEntry<bool> ItemProtection;

		internal static ConfigEntry<bool> CartProtection;

		private void Awake()
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			AutoKick = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Auto Kick", true, "Kick players caught teleporting objects. Host only.\n아이템 텔레포트 악용이 감지된 플레이어를 추방합니다. 방장에서만 동작합니다.");
			ItemProtection = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Item Protection", true, "When a player leaves or quits with items in their inventory, drop those items in the truck. Host only.\n플레이어가 인벤토리에 아이템을 넣은 채 나가거나 게임을 종료하면, 그 아이템을 트럭에 떨어뜨립니다. 방장에서만 동작합니다.");
			CartProtection = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Cart Protection", true, "Carts that would be destroyed by an extraction point or by falling out of the map are returned to the truck instead. Host only.\n추출구나 맵 밖 추락 등으로 부서질 카트를 부수지 않고 트럭으로 되돌립니다. 방장에서만 동작합니다.");
			PatchInstaller.InstallAll(new Harmony("com.sunwu.anti_Item_teleport"));
			SceneManager.sceneLoaded += delegate
			{
				PatchInstaller.TryInstallNetworkPatches();
			};
		}

		private void Update()
		{
			PatchInstaller.TryInstallNetworkPatches();
			ModEvents.TickHostCheck();
		}
	}
}
namespace AntiItemTeleport.Patches
{
	internal static class CartRescue
	{
		internal static bool Prefix(PhysGrabObjectImpactDetector __instance)
		{
			if (!__instance.isCart || !Plugin.CartProtection.Value || !RunGate.CanMoveObjects || SemiFunc.RunIsShop())
			{
				return true;
			}
			PhysGrabObject component = ((Component)__instance).GetComponent<PhysGrabObject>();
			if ((Object)(object)component == (Object)null || component.dead || !Truck.MoveTo(component))
			{
				return true;
			}
			ModEvents.Share("rescue-cart", "[Rescued] " + GuardLog.NameOf((Object)(object)component) + " -> truck");
			return false;
		}
	}
	internal static class LeaverItemDrop
	{
		private static readonly FieldRef<ItemEquippable, int> SpotIndex = AccessTools.FieldRefAccess<ItemEquippable, int>("inventorySpotIndex");

		private static readonly FieldRef<ItemEquippable, bool> ForceUnequipping = AccessTools.FieldRefAccess<ItemEquippable, bool>("isForceUnequipping");

		internal static void Prefix(Player otherPlayer)
		{
			try
			{
				Drop(otherPlayer);
			}
			catch (Exception ex)
			{
				GuardLog.Warn("item-drop-error", "Item protection failed: " + ex.Message);
			}
		}

		private static void Drop(Player leaver)
		{
			if (leaver == null || !Plugin.ItemProtection.Value || !RunGate.CanMoveObjects || SemiFunc.RunIsShop() || SemiFunc.RunIsArena() || (Object)(object)TruckSafetySpawnPoint.instance == (Object)null)
			{
				return;
			}
			PlayerAvatar val = SemiFunc.PlayerAvatarLocal();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			int viewID = PhotonView.Get((Component)(object)val).ViewID;
			List<string> list = new List<string>();
			string text = null;
			ItemEquippable[] array = Object.FindObjectsOfType<ItemEquippable>();
			foreach (ItemEquippable val2 in array)
			{
				PlayerAvatar val3 = (val2.IsEquipped() ? val2.GetOwnerPlayerAvatar() : null);
				if (!((Object)(object)val3 == (Object)null) && PhotonView.Get((Component)(object)val3).OwnerActorNr == leaver.ActorNumber)
				{
					int num = SpotIndex.Invoke(val2);
					((MonoBehaviourPun)val2).photonView.RPC("RPC_UpdateItemState", (RpcTarget)0, new object[3] { 3, -1, viewID });
					ForceUnequipping.Invoke(val2) = true;
					PhysGrabObject component = ((Component)val2).GetComponent<PhysGrabObject>();
					component.OverrideDeactivateReset();
					Truck.MoveTo(component, 0.3f * (float)list.Count);
					if (num >= 0)
					{
						StatsManager.instance.PlayerInventoryUpdate(SemiFunc.PlayerGetSteamID(val3), "", num, true);
					}
					list.Add(GuardLog.NameOf((Object)(object)component));
					if (text == null)
					{
						text = SemiFunc.PlayerGetName(val3);
					}
				}
			}
			if (list.Count > 0)
			{
				ModEvents.Share($"rescue-items:{leaver.ActorNumber}", "[Rescued] " + string.Join(", ", list) + " -> truck (" + text + " left)");
			}
		}
	}
	internal static class RpcDispatchGuard
	{
		private static readonly object KeyViewId = (byte)0;

		private static readonly object KeyMethodName = (byte)3;

		private static readonly object KeyRpcIndex = (byte)5;

		internal static bool ShouldDrop(Hashtable rpcData, Player sender)
		{
			if (rpcData == null || sender == PhotonNetwork.LocalPlayer || !RunGate.HostInGame)
			{
				return false;
			}
			string text;
			try
			{
				text = MethodName(rpcData);
			}
			catch (Exception ex)
			{
				GuardLog.Warn("dispatch-error", "Unreadable RPC: " + ex.Message);
				return false;
			}
			if (text != "SetPositionRPC")
			{
				return false;
			}
			PhotonView val = ((rpcData[KeyViewId] is int num) ? PhotonView.Find(num) : null);
			if ((Object)(object)val != (Object)null)
			{
				Detection.Handle(((Component)val).gameObject, sender);
			}
			return true;
		}

		private static string MethodName(Hashtable rpcData)
		{
			if (!((Dictionary<object, object>)(object)rpcData).ContainsKey(KeyRpcIndex))
			{
				return rpcData[KeyMethodName] as string;
			}
			int num = (short)rpcData[KeyRpcIndex];
			List<string> rpcList = PhotonNetwork.PhotonServerSettings.RpcList;
			if (num < 0 || num >= rpcList.Count)
			{
				return null;
			}
			return rpcList[num];
		}
	}
	internal static class SetPositionRpcGuard
	{
		internal static bool Prefix(PhysGrabObject __instance)
		{
			if (!RunGate.HostInGame || TeleportOrigin.InLocalCall)
			{
				return true;
			}
			if (RpcOrigin.Available && !RpcOrigin.InDispatch)
			{
				return true;
			}
			Detection.Handle(((Component)__instance).gameObject, RpcOrigin.CurrentSender);
			return false;
		}
	}
	internal static class VoidRescue
	{
		private const float VanillaVoidY = -50f;

		internal static void Prefix(PhysGrabObject __instance)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (!(((Component)__instance).transform.position.y >= -50f) && RunGate.CanMoveObjects && !__instance.dead && __instance.spawned && !((Object)(object)((Component)__instance).GetComponent<ValuableObject>() == (Object)null) && Truck.MoveTo(__instance))
			{
				ModEvents.Share("rescue", "[Rescued] " + GuardLog.NameOf((Object)(object)__instance) + " -> truck");
			}
		}
	}
}
namespace AntiItemTeleport.Core
{
	internal static class Detection
	{
		private static readonly HashSet<int> Kicked = new HashSet<int>();

		private static FieldRef<SteamManager, Lobby> _currentLobby;

		internal static void Handle(GameObject target, Player sender)
		{
			try
			{
				if (!((Object)(object)target == (Object)null) && !IsRedundantMove(target))
				{
					string kicked = (Kick(sender) ? " (kicked)" : "");
					Player obj = sender;
					ModEvents.Share($"tp:{((obj != null) ? new int?(obj.ActorNumber) : ((int?)null))}", () => "[Teleport] " + Describe(sender) + " -> " + Category(target) + ": " + GuardLog.NameOf((Object)(object)target) + kicked);
				}
			}
			catch (Exception ex)
			{
				GuardLog.Warn("detect-error", "Detection failed: " + ex.Message);
			}
		}

		private static bool IsRedundantMove(GameObject target)
		{
			EnemyParent componentInParent = target.GetComponentInParent<EnemyParent>();
			if ((!((Object)(object)componentInParent != (Object)null) || !((Object)(object)((Component)componentInParent).GetComponentInChildren<EnemySlowMouth>(true) != (Object)null)) && (!((Object)(object)target.GetComponentInParent<ItemMine>() != (Object)null) || !SemiFunc.RunIsShop()))
			{
				return (Object)(object)target.GetComponentInParent<PlayerTumble>() != (Object)null;
			}
			return true;
		}

		private static string Category(GameObject target)
		{
			if ((Object)(object)target.GetComponent<CosmeticWorldObject>() != (Object)null)
			{
				return "Cosmetic box";
			}
			if ((Object)(object)target.GetComponent<ValuableObject>() != (Object)null)
			{
				return "Valuable";
			}
			if ((Object)(object)target.GetComponent<ItemAttributes>() != (Object)null)
			{
				return "Item";
			}
			if ((Object)(object)target.GetComponentInParent<EnemyParent>() != (Object)null)
			{
				return "Monster";
			}
			if ((Object)(object)target.GetComponentInParent<PlayerDeathHead>() != (Object)null)
			{
				return "Death head";
			}
			if ((Object)(object)target.GetComponent<PhysGrabCart>() != (Object)null)
			{
				return "Cart";
			}
			return "Object";
		}

		internal static string Describe(Player player)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			if (player == null)
			{
				return "unknown";
			}
			PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonPlayer(player);
			string text = (((Object)(object)val != (Object)null) ? SemiFunc.PlayerGetSteamID(val) : null);
			Friend? val2 = LobbyMember(player.UserId);
			if (!val2.HasValue)
			{
				string obj = (((Object)(object)val != (Object)null) ? SemiFunc.PlayerGetName(val) : player.NickName);
				string text2 = ((!string.IsNullOrEmpty(player.UserId)) ? player.UserId : (text ?? "?"));
				return obj + " (" + text2 + ", unverified)";
			}
			Friend value = val2.Value;
			string text3 = value.Id.Value.ToString();
			value = val2.Value;
			string text4 = ((Friend)(ref value)).Name + " (" + text3 + ")";
			if (text == null || !(text != text3))
			{
				return text4;
			}
			return text4 + " [claims " + text + "]";
		}

		private static Friend? LobbyMember(string userId)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(userId) || (Object)(object)SteamManager.instance == (Object)null)
			{
				return null;
			}
			try
			{
				if (_currentLobby == null)
				{
					_currentLobby = AccessTools.FieldRefAccess<SteamManager, Lobby>("currentLobby");
				}
				foreach (Friend member in ((Lobby)(ref _currentLobby.Invoke(SteamManager.instance))).Members)
				{
					if (member.Id.Value.ToString() == userId)
					{
						return member;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		internal static void PublishUserId(EnterRoomParams enterRoomParams)
		{
			if (enterRoomParams?.RoomOptions != null)
			{
				enterRoomParams.RoomOptions.PublishUserId = true;
			}
		}

		private static bool Kick(Player sender)
		{
			if (sender == null || !Plugin.AutoKick.Value)
			{
				return false;
			}
			if (Kicked.Contains(sender.ActorNumber))
			{
				return true;
			}
			PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonPlayer(sender);
			if ((Object)(object)val == (Object)null || (Object)(object)NetworkManager.instance == (Object)null)
			{
				return false;
			}
			NetworkManager.instance.KickPlayer(val);
			Kicked.Add(sender.ActorNumber);
			return true;
		}
	}
	internal static class GuardLog
	{
		private static readonly Dictionary<string, float> NextEmit = new Dictionary<string, float>();

		private static readonly Dictionary<string, int> Suppressed = new Dictionary<string, int>();

		internal static bool Warn(string key, string message)
		{
			return Warn(key, () => message) != null;
		}

		internal static string Warn(string key, Func<string> build)
		{
			float unscaledTime = Time.unscaledTime;
			Suppressed.TryGetValue(key, out var value);
			if (NextEmit.TryGetValue(key, out var value2) && unscaledTime < value2)
			{
				Suppressed[key] = value + 1;
				return null;
			}
			NextEmit[key] = unscaledTime + 1f;
			Suppressed[key] = 0;
			string text = build();
			Plugin.Log.LogWarning((object)((value > 0) ? $"{text} (+{value})" : text));
			return text;
		}

		internal static string NameOf(Object obj)
		{
			return obj.name.Replace("(Clone)", "").Trim();
		}
	}
	internal static class ModEvents
	{
		private const byte Code = 171;

		private const byte Report = 0;

		private const byte Ping = 1;

		private const byte Pong = 2;

		private static bool _listening;

		private static string _checkedRoom;

		private static float _pingSentAt = -1f;

		internal static void Listen()
		{
			try
			{
				PhotonNetwork.NetworkingClient.EventReceived += OnEvent;
				_listening = true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Patch failed: mod events (" + ex.Message + ")"));
			}
		}

		internal static void Share(string key, string line)
		{
			Share(key, () => line);
		}

		internal static void Share(string key, Func<string> build)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			string text = GuardLog.Warn(key, build);
			if (text != null)
			{
				Send(new object[2]
				{
					(byte)0,
					text
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				});
			}
		}

		internal static void TickHostCheck()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			if (_listening)
			{
				if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient || PhotonNetwork.CurrentRoom == null)
				{
					_checkedRoom = null;
					_pingSentAt = -1f;
				}
				else if (PhotonNetwork.CurrentRoom.Name != _checkedRoom)
				{
					_checkedRoom = PhotonNetwork.CurrentRoom.Name;
					_pingSentAt = Time.unscaledTime;
					Send(new object[2]
					{
						(byte)1,
						"1.4.0"
					}, new RaiseEventOptions
					{
						Receivers = (ReceiverGroup)2
					});
				}
				else if (_pingSentAt >= 0f && Time.unscaledTime - _pingSentAt > 5f)
				{
					_pingSentAt = -1f;
					Plugin.Log.LogWarning((object)"Host does not have Anti Item Teleport.");
				}
			}
		}

		private static void Send(object[] content, RaiseEventOptions options)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (PhotonNetwork.InRoom)
				{
					PhotonNetwork.RaiseEvent((byte)171, (object)content, options, SendOptions.SendReliable);
				}
			}
			catch (Exception ex)
			{
				GuardLog.Warn("event-send", "Mod event not sent: " + ex.Message);
			}
		}

		private static void OnEvent(EventData e)
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			if (e.Code == 171 && e.CustomData is object[] array && array.Length >= 2 && array[0] is byte b)
			{
				Player masterClient = PhotonNetwork.MasterClient;
				bool flag = masterClient != null && e.Sender == masterClient.ActorNumber;
				if (b == 0 && flag && array[1] is string text)
				{
					GuardLog.Warn("host:" + text.Split(' ')[0], "[Host] " + text);
				}
				else if (b == 1 && PhotonNetwork.IsMasterClient)
				{
					object[] content = new object[2]
					{
						(byte)2,
						"1.4.0"
					};
					RaiseEventOptions val = new RaiseEventOptions();
					val.TargetActors = new int[1] { e.Sender };
					Send(content, val);
				}
				else if (b == 2 && flag && _pingSentAt >= 0f)
				{
					_pingSentAt = -1f;
					Plugin.Log.LogInfo((object)string.Format("Host has {0} {1}.", "Anti Item Teleport", array[1]));
				}
			}
		}
	}
	internal static class PatchInstaller
	{
		private static Harmony _harmony;

		private static bool _networkPatched;

		internal static void InstallAll(Harmony harmony)
		{
			_harmony = harmony;
			if (Apply("PhysGrabObject.Teleport", AccessTools.Method(typeof(PhysGrabObject), "Teleport", new Type[2]
			{
				typeof(Vector3),
				typeof(Quaternion)
			}, (Type[])null), Hook(typeof(TeleportOrigin), "Enter"), Hook(typeof(TeleportOrigin), "Leave")))
			{
				Apply("PhysGrabObject.SetPositionRPC", AccessTools.Method(typeof(PhysGrabObject), "SetPositionRPC", (Type[])null, (Type[])null), Hook(typeof(SetPositionRpcGuard), "Prefix"));
			}
			Apply("PhysGrabObject.Update", AccessTools.Method(typeof(PhysGrabObject), "Update", (Type[])null, (Type[])null), Hook(typeof(VoidRescue), "Prefix"));
			Apply("PhysGrabObjectImpactDetector.DestroyObject", AccessTools.Method(typeof(PhysGrabObjectImpactDetector), "DestroyObject", (Type[])null, (Type[])null), Hook(typeof(CartRescue), "Prefix"));
		}

		internal static void TryInstallNetworkPatches()
		{
			if (!_networkPatched && _harmony != null && !((Object)(object)GameObject.Find("PhotonMono") == (Object)null))
			{
				_networkPatched = true;
				ModEvents.Listen();
				string[] array = new string[2] { "OpCreateRoom", "OpJoinOrCreateRoom" };
				foreach (string text in array)
				{
					Apply("LoadBalancingClient." + text, AccessTools.Method(typeof(LoadBalancingClient), text, (Type[])null, (Type[])null), Hook(typeof(Detection), "PublishUserId"));
				}
				Apply("NetworkManager.OnPlayerLeftRoom", AccessTools.Method(typeof(NetworkManager), "OnPlayerLeftRoom", (Type[])null, (Type[])null), Hook(typeof(LeaverItemDrop), "Prefix"));
				RpcOrigin.Available = Apply("PhotonNetwork.ExecuteRpc", AccessTools.Method(typeof(PhotonNetwork), "ExecuteRpc", (Type[])null, (Type[])null), Hook(typeof(RpcOrigin), "Enter"), Hook(typeof(RpcOrigin), "Leave"));
				Plugin.Log.LogInfo((object)(RpcOrigin.Available ? "Anti Item Teleport 1.4.0 active." : "Anti Item Teleport 1.4.0 active (fallback layer only)."));
			}
		}

		private static HarmonyMethod Hook(Type type, string method)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			return new HarmonyMethod(type, method, (Type[])null);
		}

		private static bool Apply(string label, MethodBase target, HarmonyMethod prefix, HarmonyMethod finalizer = null)
		{
			try
			{
				if (target == null)
				{
					throw new MissingMethodException("not found");
				}
				_harmony.Patch(target, prefix, (HarmonyMethod)null, (HarmonyMethod)null, finalizer, (HarmonyMethod)null);
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Patch failed: " + label + " (" + ex.Message + ")"));
				return false;
			}
		}
	}
	internal static class RpcOrigin
	{
		internal static bool Available;

		private static readonly List<Player> Senders = new List<Player>();

		internal static bool InDispatch => Senders.Count > 0;

		internal static Player CurrentSender
		{
			get
			{
				if (Senders.Count <= 0)
				{
					return null;
				}
				return Senders[Senders.Count - 1];
			}
		}

		internal static bool Enter(Hashtable rpcData, Player sender)
		{
			if (Senders.Count > 64)
			{
				Senders.Clear();
			}
			Senders.Add(sender);
			return !RpcDispatchGuard.ShouldDrop(rpcData, sender);
		}

		internal static void Leave()
		{
			if (Senders.Count > 0)
			{
				Senders.RemoveAt(Senders.Count - 1);
			}
		}
	}
	internal static class RunGate
	{
		private static int _frame = -1;

		private static bool _hostInGame;

		private static bool _levelReady;

		internal static bool HostInGame
		{
			get
			{
				Refresh();
				return _hostInGame;
			}
		}

		internal static bool CanMoveObjects
		{
			get
			{
				Refresh();
				if (_hostInGame)
				{
					return _levelReady;
				}
				return false;
			}
		}

		private static void Refresh()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Invalid comparison between Unknown and I4
			if (_frame == Time.frameCount)
			{
				return;
			}
			_frame = Time.frameCount;
			try
			{
				_hostInGame = (Object)(object)RunManager.instance != (Object)null && !SemiFunc.MenuLevel() && SemiFunc.IsMasterClientOrSingleplayer();
				_levelReady = (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated && (Object)(object)GameDirector.instance != (Object)null && (int)GameDirector.instance.currentState == 2;
			}
			catch
			{
				_hostInGame = (_levelReady = false);
			}
		}
	}
	internal static class TeleportOrigin
	{
		private static int _depth;

		internal static bool InLocalCall => _depth > 0;

		internal static void Enter()
		{
			if (++_depth > 64)
			{
				_depth = 0;
			}
		}

		internal static void Leave()
		{
			if (_depth > 0)
			{
				_depth--;
			}
		}
	}
	internal static class Truck
	{
		internal static bool MoveTo(PhysGrabObject obj, float height = 0f)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			TruckSafetySpawnPoint instance = TruckSafetySpawnPoint.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			if ((Object)(object)obj.rb != (Object)null)
			{
				obj.rb.velocity = Vector3.zero;
				obj.rb.angularVelocity = Vector3.zero;
			}
			obj.Teleport(((Component)instance).transform.position + Vector3.up * height, ((Component)instance).transform.rotation);
			return true;
		}
	}
}