Decompiled source of PocketCart v2.0.0

RepoPocketCart.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using PocketCart.Core;
using PocketCart.Patches;
using ScalerCore;
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("RepoPocketCart")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0")]
[assembly: AssemblyProduct("Pocket Cart")]
[assembly: AssemblyTitle("RepoPocketCart")]
[assembly: AssemblyVersion("2.0.0.0")]
namespace PocketCart
{
	[BepInPlugin("com.sunwu.pocket_cart", "Pocket Cart", "2.0.0")]
	[BepInIncompatibility("empress.repo.pocketdimensioncart")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static readonly bool LateJoinLoaded = Chainloader.PluginInfos.ContainsKey("repolatejoin.unified");

		internal static Runner Runner;

		private void Awake()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			GameAccess.Resolve();
			PatchInstaller.InstallAll(new Harmony("com.sunwu.pocket_cart"));
			GameObject val = new GameObject("PocketCart")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			Runner = val.AddComponent<Runner>();
			SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode mode)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				if ((int)mode == 0)
				{
					VaultRegistry.Reset();
				}
			};
			Log.LogInfo((object)("Pocket Cart 2.0.0 ready - carts store their contents out of sight (host-authoritative)." + (LateJoinLoaded ? " RepoLateJoin found: cart rescue / leaver items left to it." : "")));
		}
	}
	internal sealed class Runner : MonoBehaviour
	{
		private void Update()
		{
			CartRescue.Tick();
		}
	}
	internal static class PluginInfo
	{
		internal const string Guid = "com.sunwu.pocket_cart";

		internal const string Name = "Pocket Cart";

		internal const string Version = "2.0.0";

		internal const string ReplacedGuid = "empress.repo.pocketdimensioncart";

		internal const string LateJoinGuid = "repolatejoin.unified";
	}
}
namespace PocketCart.Patches
{
	internal static class CartScreenTotal
	{
		private static bool _warned;

		internal static void Prefix(ValueScreen __instance, ref int newValue)
		{
			try
			{
				CartVault cartVault = VaultRegistry.FindByScreen(__instance);
				if ((Object)(object)cartVault != (Object)null)
				{
					newValue += cartVault.CloakedValue() + cartVault.LegacyStoredValue;
				}
			}
			catch (Exception ex)
			{
				if (!_warned)
				{
					_warned = true;
					Plugin.Log.LogWarning((object)("Cart screen total failed, showing the vanilla value: " + ex.Message));
				}
			}
		}
	}
	internal static class CartSpawnHook
	{
		internal static void Postfix(PhysGrabCart __instance)
		{
			if (!Object.op_Implicit((Object)(object)__instance))
			{
				return;
			}
			try
			{
				if (RunGate.IsRunLevel && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<CartVault>()))
				{
					((Component)__instance).gameObject.AddComponent<CartVault>();
					PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
					if (Object.op_Implicit((Object)(object)component))
					{
						component.RefreshRpcMonoBehaviourCache();
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not attach a vault to cart '" + ((Object)__instance).name + "': " + ex.Message));
			}
		}
	}
	internal static class CartRescuePatch
	{
		internal static bool Prefix(PhysGrabObjectImpactDetector __instance)
		{
			try
			{
				return !CartRescue.On || !CartRescue.Protects(__instance) || !CartRescue.Rescue(((Component)__instance).GetComponent<PhysGrabObject>());
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Cart rescue failed, letting the game destroy it: " + ex.Message));
				return true;
			}
		}
	}
	internal static class PlayerLeftHook
	{
		internal static void Postfix(Player otherPlayer)
		{
			try
			{
				if (PhotonNetwork.IsMasterClient && !((Object)(object)Plugin.Runner == (Object)null))
				{
					((MonoBehaviour)Plugin.Runner).StartCoroutine(LeaverItems.ReleaseAfterLeave());
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not schedule the leaver item release: " + ex.Message));
			}
		}
	}
}
namespace PocketCart.Core
{
	internal static class CartRescue
	{
		private const float CheckEvery = 0.25f;

		private const float ListEvery = 3f;

		private const float LookUp = 40f;

		private static readonly List<PhysGrabObject> Watched = new List<PhysGrabObject>();

		private static float _nextCheck;

		private static float _nextList;

		internal static bool On
		{
			get
			{
				if (!Plugin.LateJoinLoaded && ModConfig.RescueCarts.Value)
				{
					return HostCanMoveObjects();
				}
				return false;
			}
		}

		internal static bool Protects(PhysGrabObjectImpactDetector impact)
		{
			if (!impact.isCart)
			{
				return (Object)(object)((Component)impact).GetComponent<ItemVehicle>() != (Object)null;
			}
			return true;
		}

		internal static bool Rescue(PhysGrabObject obj)
		{
			if ((Object)(object)obj == (Object)null || obj.dead)
			{
				return false;
			}
			CartVault component = ((Component)obj).GetComponent<CartVault>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.LeaveContentsAtExtraction();
			}
			if (!MoveToTruck(obj))
			{
				return false;
			}
			Plugin.Log.LogInfo((object)("[Rescued] " + ((Object)obj).name + " -> truck"));
			return true;
		}

		internal static bool MoveToTruck(PhysGrabObject obj, float height = 0f)
		{
			//IL_005c: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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)
			TruckSafetySpawnPoint instance = TruckSafetySpawnPoint.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)obj == (Object)null)
			{
				return false;
			}
			if ((Object)(object)obj.rb != (Object)null && !obj.rb.isKinematic)
			{
				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;
		}

		internal static void Tick()
		{
			if (Time.unscaledTime < _nextCheck)
			{
				return;
			}
			_nextCheck = Time.unscaledTime + 0.25f;
			if (!On)
			{
				Watched.Clear();
				_nextList = 0f;
				return;
			}
			if (Time.unscaledTime >= _nextList)
			{
				_nextList = Time.unscaledTime + 3f;
				Watched.Clear();
				PhysGrabCart[] array = Object.FindObjectsOfType<PhysGrabCart>();
				for (int i = 0; i < array.Length; i++)
				{
					Watch((Component)(object)array[i]);
				}
				ItemVehicle[] array2 = Object.FindObjectsOfType<ItemVehicle>();
				for (int i = 0; i < array2.Length; i++)
				{
					Watch((Component)(object)array2[i]);
				}
			}
			foreach (PhysGrabObject item in Watched)
			{
				if (!((Object)(object)item == (Object)null) && !item.dead && item.spawned && !((Object)(object)item.rb == (Object)null) && !item.rb.isKinematic && InDeathPit(item))
				{
					Rescue(item);
				}
			}
		}

		internal static bool HostCanMoveObjects()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Invalid comparison between Unknown and I4
			try
			{
				return (Object)(object)RunManager.instance != (Object)null && !SemiFunc.MenuLevel() && !SemiFunc.RunIsShop() && SemiFunc.IsMasterClientOrSingleplayer() && (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated && (Object)(object)GameDirector.instance != (Object)null && (int)GameDirector.instance.currentState == 2;
			}
			catch
			{
				return false;
			}
		}

		private static void Watch(Component part)
		{
			PhysGrabObject component = part.GetComponent<PhysGrabObject>();
			if ((Object)(object)component != (Object)null)
			{
				Watched.Add(component);
			}
		}

		private static bool InDeathPit(PhysGrabObject obj)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			Vector3 centerPoint = obj.centerPoint;
			int mask = LayerMask.GetMask(new string[1] { "Triggers" });
			Collider[] array = Physics.OverlapSphere(centerPoint, 0.3f, mask, (QueryTriggerInteraction)2);
			for (int i = 0; i < array.Length; i++)
			{
				if (IsPit(array[i]))
				{
					return true;
				}
			}
			RaycastHit[] array2 = Physics.RaycastAll(centerPoint, Vector3.up, 40f, mask, (QueryTriggerInteraction)2);
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val = array2[i];
				if (IsPit(((RaycastHit)(ref val)).collider) && !SolidAbove(obj, centerPoint, ((RaycastHit)(ref val)).distance))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsPit(Collider c)
		{
			HurtCollider componentInParent = ((Component)c).GetComponentInParent<HurtCollider>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return componentInParent.deathPit;
			}
			return false;
		}

		private static bool SolidAbove(PhysGrabObject self, Vector3 at, float distance)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit[] array = Physics.RaycastAll(at, Vector3.up, distance, LayerMask.GetMask(new string[1] { "Default" }), (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val = array[i];
				if (!((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(((Component)self).transform))
				{
					return true;
				}
			}
			return false;
		}
	}
	internal sealed class CartVault : MonoBehaviour
	{
		private struct Slot
		{
			public PhysGrabObject Item;

			public int Key;

			public int Cell;
		}

		private const float IntakeScanInterval = 0.1f;

		private const float IntakeSettleSeconds = 0.25f;

		private const float ShieldInterval = 0.5f;

		private const float ShieldSeconds = 1.5f;

		private const float YardDriftSqr = 0.25f;

		private const float YardLift = 0.05f;

		private const float SpillSpacing = 0.6f;

		private const float SpillLift = 0.5f;

		private const float SpillShieldSeconds = 5f;

		private const float SpillImpactMuteSeconds = 1f;

		private const float ReintakeLockSeconds = 2.5f;

		private const float CrushRetrySeconds = 1f;

		private static readonly int[] SpillCellOrder = new int[9] { 4, 1, 3, 5, 7, 0, 2, 6, 8 };

		private readonly List<Slot> _slots = new List<Slot>();

		private readonly Dictionary<int, float> _settleSince = new Dictionary<int, float>();

		private readonly HashSet<int> _seenThisScan = new HashSet<int>();

		private readonly List<int> _settleStale = new List<int>();

		private readonly Dictionary<int, float> _crushRetryAt = new Dictionary<int, float>();

		private readonly ValueCarrier _carrier = new ValueCarrier();

		private int _legacyStoredValue;

		private PhysGrabCart _cart;

		private PhysGrabObject _cartBody;

		private ItemEquippable _equip;

		private RoomVolumeCheck _cartRooms;

		private Transform _bay;

		private bool _ready;

		private int _yardIndex = -1;

		private bool _docked;

		private bool _inExtraction;

		private bool _hasDockedPose;

		private Vector3 _dockedCenter;

		private Quaternion _dockedRotation = Quaternion.identity;

		private float _nextIntakeScan;

		private float _nextShield;

		private const float CloakInterval = 0.1f;

		private readonly List<PhysGrabObject> _cloaked = new List<PhysGrabObject>();

		private readonly List<PhysGrabObject> _wanted = new List<PhysGrabObject>();

		private float _nextCloak;

		internal int ViewId { get; private set; }

		internal int LegacyStoredValue => _legacyStoredValue;

		[PunRPC]
		private void PocketDimensionSyncStoredTotals(int count, int value, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMultiplayer() || info.Sender == PhotonNetwork.MasterClient)
			{
				_legacyStoredValue = Mathf.Max(0, value);
			}
		}

		private void Start()
		{
			_cart = ((Component)this).GetComponent<PhysGrabCart>();
			_cartBody = ((Component)this).GetComponent<PhysGrabObject>();
			_equip = ((Component)this).GetComponent<ItemEquippable>();
			_cartRooms = ((Component)this).GetComponent<RoomVolumeCheck>();
			_bay = ((Component)this).transform.Find("In Cart");
			PhotonView component = ((Component)this).GetComponent<PhotonView>();
			ViewId = (Object.op_Implicit((Object)(object)component) ? component.ViewID : 0);
			if (!Object.op_Implicit((Object)(object)_cart) || !Object.op_Implicit((Object)(object)_cartBody) || !Object.op_Implicit((Object)(object)_bay))
			{
				Plugin.Log.LogWarning((object)("Cart '" + ((Object)this).name + "' has no 'In Cart' volume, leaving it vanilla."));
				Object.Destroy((Object)(object)this);
			}
			else
			{
				_ready = true;
				VaultRegistry.Register(this, _cart.valueScreen);
			}
		}

		private void Update()
		{
			if (_ready && RunGate.InRunLevel)
			{
				float time = Time.time;
				if (RunGate.IsHost)
				{
					HostTick(time);
				}
				RefreshCloaks(time);
			}
		}

		private void LateUpdate()
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			if (!_ready || !RunGate.InRunLevel || !RunGate.IsHost)
			{
				return;
			}
			if (_inExtraction && _slots.Count > 0)
			{
				PresentInCart();
			}
			if (Object.op_Implicit((Object)(object)_carrier.Body))
			{
				if (_docked && !_inExtraction && _slots.Count > 0 && _carrier.IsReady(Time.time))
				{
					Quaternion rotation = YawOnly(_bay.rotation);
					_carrier.Place(PivotFor(_carrier.Body, _bay.position, rotation), rotation);
				}
				else
				{
					_carrier.Place(VaultYard.CarrierPark(YardIndex()), Quaternion.identity);
				}
			}
		}

		private void OnDisable()
		{
			if (_ready)
			{
				UncloakAll();
				if (RunGate.IsHost && RunGate.Playing)
				{
					SpillAll("cart disabled");
					_carrier.Destroy();
				}
			}
		}

		private void OnDestroy()
		{
			if (_ready)
			{
				_ready = false;
				UncloakAll();
				if (RunGate.IsHost && RunGate.Playing)
				{
					SpillAll("cart destroyed");
					_carrier.Destroy();
				}
				VaultRegistry.Unregister(this);
			}
		}

		private void HostTick(float now)
		{
			//IL_0021: 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)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			PruneMissing();
			_docked = IsDocked();
			if (_docked)
			{
				_dockedCenter = _bay.position;
				_dockedRotation = _bay.rotation;
				_hasDockedPose = true;
			}
			bool inExtraction = _inExtraction;
			_inExtraction = _docked && InExtraction();
			if (inExtraction && !_inExtraction)
			{
				foreach (Slot slot in _slots)
				{
					if (Object.op_Implicit((Object)(object)slot.Item))
					{
						slot.Item.Teleport(YardPivot(slot), Quaternion.identity);
					}
				}
			}
			if (_slots.Count > 0 && now >= _nextShield)
			{
				_nextShield = now + 0.5f;
				foreach (Slot slot2 in _slots)
				{
					if (Object.op_Implicit((Object)(object)slot2.Item))
					{
						KeepParked(slot2);
					}
				}
			}
			if (now >= _nextIntakeScan)
			{
				_nextIntakeScan = now + 0.1f;
				if (_docked)
				{
					ScanIntake(now);
				}
				else
				{
					_settleSince.Clear();
				}
			}
			_carrier.Tick(_cart, (!_inExtraction) ? StoredValue() : 0, VaultYard.CarrierPark(YardIndex()), now);
		}

		private void RefreshCloaks(float now)
		{
			if (now < _nextCloak)
			{
				return;
			}
			_nextCloak = now + 0.1f;
			_wanted.Clear();
			if (RunGate.IsHost)
			{
				if (_inExtraction)
				{
					foreach (Slot slot in _slots)
					{
						if (Object.op_Implicit((Object)(object)slot.Item))
						{
							_wanted.Add(slot.Item);
						}
					}
				}
			}
			else
			{
				CollectHostPresented(_wanted);
			}
			foreach (PhysGrabObject item in _wanted)
			{
				Cloak.Set(item, hidden: true);
				if (!_cloaked.Contains(item))
				{
					_cloaked.Add(item);
				}
			}
			for (int num = _cloaked.Count - 1; num >= 0; num--)
			{
				PhysGrabObject val = _cloaked[num];
				if (!Object.op_Implicit((Object)(object)val) || !_wanted.Contains(val))
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						Cloak.Set(val, hidden: false);
					}
					_cloaked.RemoveAt(num);
				}
			}
		}

		private void CollectHostPresented(List<PhysGrabObject> into)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			List<PhysGrabObject> list = GameAccess.AllBodies();
			if (list == null)
			{
				return;
			}
			foreach (PhysGrabObject item in list)
			{
				if (Object.op_Implicit((Object)(object)item) && !((Object)(object)item == (Object)(object)_cartBody) && GameAccess.HostKinematic(item) == true && InBay(item.midPoint) && (Object.op_Implicit((Object)(object)((Component)item).GetComponent<ValuableObject>()) || Object.op_Implicit((Object)(object)((Component)item).GetComponent<ItemValuableBox>()) || Object.op_Implicit((Object)(object)((Component)item).GetComponent<CosmeticWorldObject>())))
				{
					into.Add(item);
				}
			}
		}

		private bool InBay(Vector3 point)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = _bay.InverseTransformPoint(point);
			if (Mathf.Abs(val.x) <= 0.55f && Mathf.Abs(val.y) <= 0.55f)
			{
				return Mathf.Abs(val.z) <= 0.55f;
			}
			return false;
		}

		internal int CloakedValue()
		{
			int num = 0;
			foreach (PhysGrabObject item in _cloaked)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					num += ValueOf(item);
				}
			}
			return num;
		}

		private static int ValueOf(PhysGrabObject item)
		{
			ValuableObject component = ((Component)item).GetComponent<ValuableObject>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return GameAccess.DollarValue(component);
			}
			ItemValuableBox component2 = ((Component)item).GetComponent<ItemValuableBox>();
			if (!Object.op_Implicit((Object)(object)component2))
			{
				return 0;
			}
			return (int)component2.CurrentValue;
		}

		private void UncloakAll()
		{
			foreach (PhysGrabObject item in _cloaked)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					Cloak.Set(item, hidden: false);
				}
			}
			_cloaked.Clear();
		}

		private bool IsDocked()
		{
			if (!((Behaviour)_cart).isActiveAndEnabled)
			{
				return false;
			}
			Rigidbody rb = _cartBody.rb;
			if (Object.op_Implicit((Object)(object)rb) && !rb.detectCollisions)
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)_equip) && (_equip.IsEquipped() || GameAccess.InEquipTransition(_equip)))
			{
				return false;
			}
			return true;
		}

		private bool InExtraction()
		{
			if (!Object.op_Implicit((Object)(object)_cartRooms) || _cartRooms.CurrentRooms == null)
			{
				return false;
			}
			foreach (RoomVolume currentRoom in _cartRooms.CurrentRooms)
			{
				if (Object.op_Implicit((Object)(object)currentRoom) && currentRoom.Extraction)
				{
					return true;
				}
			}
			return false;
		}

		private int StoredValue()
		{
			int num = 0;
			foreach (Slot slot in _slots)
			{
				if (Object.op_Implicit((Object)(object)slot.Item))
				{
					num += ValueOf(slot.Item);
				}
			}
			return num;
		}

		private int YardIndex()
		{
			if (_yardIndex < 0)
			{
				_yardIndex = VaultRegistry.NextYardIndex();
			}
			return _yardIndex;
		}

		private void ScanIntake(float now)
		{
			_seenThisScan.Clear();
			List<CartObject> list = GameAccess.CartEntries(_cart.physGrabInCart);
			if (list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					PhysGrabObject val = list[i]?.physGrabObject;
					if (ModConfig.KillEnemiesInCart.Value)
					{
						TryCrushEnemy(val, now);
					}
					if (_inExtraction || !IsIntakeCandidate(val, now))
					{
						continue;
					}
					int instanceID = ((Object)val).GetInstanceID();
					if (_seenThisScan.Add(instanceID))
					{
						if (!_settleSince.TryGetValue(instanceID, out var value))
						{
							_settleSince[instanceID] = now;
						}
						else if (now - value >= 0.25f)
						{
							Admit(val);
						}
					}
				}
			}
			_settleStale.Clear();
			foreach (int key in _settleSince.Keys)
			{
				if (!_seenThisScan.Contains(key))
				{
					_settleStale.Add(key);
				}
			}
			foreach (int item in _settleStale)
			{
				_settleSince.Remove(item);
			}
		}

		private void TryCrushEnemy(PhysGrabObject item, float now)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				return;
			}
			EnemyRigidbody componentInParent = ((Component)item).GetComponentInParent<EnemyRigidbody>();
			Enemy val = (Object.op_Implicit((Object)(object)componentInParent) ? componentInParent.enemy : ((Component)item).GetComponentInParent<Enemy>());
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			PhysGrabObjectImpactDetector component = ((Component)item).GetComponent<PhysGrabObjectImpactDetector>();
			if (!Object.op_Implicit((Object)(object)component) || !component.inCart || (Object)(object)GameAccess.CartOf(component) != (Object)(object)_cart)
			{
				return;
			}
			int instanceID = ((Object)val).GetInstanceID();
			if (_crushRetryAt.TryGetValue(instanceID, out var value) && now < value)
			{
				return;
			}
			_crushRetryAt[instanceID] = now + 1f;
			try
			{
				GameAccess.KillEnemy(val);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)$"Could not kill enemy '{((Object)val).name}' in cart {ViewId}: {ex.Message}");
			}
		}

		private bool IsIntakeCandidate(PhysGrabObject item, float now)
		{
			if (!Object.op_Implicit((Object)(object)item) || (Object)(object)item == (Object)(object)_cartBody || item.dead || !item.spawned || !((Behaviour)item).isActiveAndEnabled)
			{
				return false;
			}
			if (item.grabbed || item.playerGrabbing.Count > 0)
			{
				return false;
			}
			Rigidbody rb = item.rb;
			if (!Object.op_Implicit((Object)(object)rb) || rb.isKinematic)
			{
				return false;
			}
			if (VaultRegistry.IsHeld(item) || VaultRegistry.IsIntakeLocked(item, now))
			{
				return false;
			}
			PhysGrabObjectImpactDetector component = ((Component)item).GetComponent<PhysGrabObjectImpactDetector>();
			if (!Object.op_Implicit((Object)(object)component) || !component.inCart || (Object)(object)GameAccess.CartOf(component) != (Object)(object)_cart)
			{
				return false;
			}
			return IsSellable(item);
		}

		private static bool IsSellable(PhysGrabObject item)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			ValuableObject component = ((Component)item).GetComponent<ValuableObject>();
			if (Object.op_Implicit((Object)(object)component))
			{
				if (GameAccess.DollarValueReady(component))
				{
					return !GameAccess.IsClaimedByValuableBox(item);
				}
				return false;
			}
			ItemValuableBox component2 = ((Component)item).GetComponent<ItemValuableBox>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				if ((int)component2.currentState != 0)
				{
					return (int)component2.currentState == 4;
				}
				return true;
			}
			CosmeticWorldObject component3 = ((Component)item).GetComponent<CosmeticWorldObject>();
			if (Object.op_Implicit((Object)(object)component3))
			{
				return !GameAccess.IsExploding(component3);
			}
			return false;
		}

		private void Admit(PhysGrabObject item)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			VaultYard.EnsureFloor();
			ParkedBody.Hold(item);
			Slot slot = new Slot
			{
				Item = item,
				Key = ((Object)item).GetInstanceID(),
				Cell = FreeCell()
			};
			_slots.Add(slot);
			VaultRegistry.MarkHeld(item, this);
			_settleSince.Remove(slot.Key);
			item.Teleport(YardPivot(slot), Quaternion.identity);
			Shield(item, 1.5f, 1.5f);
			GameAccess.HoldInCart(((Component)item).GetComponent<PhysGrabObjectImpactDetector>(), _cart, 1.5f);
			ShrinkBridge.Shrink(item);
		}

		private void KeepParked(Slot slot)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			PhysGrabObject item = slot.Item;
			Shield(item, 1.5f, 1.5f);
			GameAccess.HoldInCart(((Component)item).GetComponent<PhysGrabObjectImpactDetector>(), _cart, 1.5f);
			if (!_inExtraction)
			{
				Vector3 val = YardPivot(slot);
				Vector3 val2 = ((Component)item).transform.position - val;
				if (((Vector3)(ref val2)).sqrMagnitude > 0.25f)
				{
					item.Teleport(val, Quaternion.identity);
				}
			}
		}

		private void PresentInCart()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = _bay.position;
			Quaternion val = YawOnly(_bay.rotation);
			foreach (Slot slot in _slots)
			{
				PhysGrabObject item = slot.Item;
				if (!Object.op_Implicit((Object)(object)item))
				{
					continue;
				}
				Cloak.Set(item, hidden: true);
				if (!_cloaked.Contains(item))
				{
					_cloaked.Add(item);
				}
				Rigidbody rb = item.rb;
				Vector3 val2 = PivotFor(item, position, val);
				Transform transform = ((Component)item).transform;
				Vector3 val3 = transform.position - val2;
				if (!(((Vector3)(ref val3)).sqrMagnitude < 1E-06f) || !(Quaternion.Angle(transform.rotation, val) < 0.05f))
				{
					transform.SetPositionAndRotation(val2, val);
					if (Object.op_Implicit((Object)(object)rb))
					{
						rb.position = val2;
						rb.rotation = val;
					}
				}
			}
		}

		private int FreeCell()
		{
			int num = 0;
			while (true)
			{
				bool flag = false;
				foreach (Slot slot in _slots)
				{
					if (slot.Cell == num)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					break;
				}
				num++;
			}
			return num;
		}

		private Vector3 YardPivot(Slot slot)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//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)
			Vector3 val = VaultYard.CellFloor(YardIndex(), slot.Cell);
			float num = slot.Item.boundingBox.y * 0.5f;
			return PivotFor(slot.Item, val + Vector3.up * (num + 0.05f), Quaternion.identity);
		}

		private void PruneMissing()
		{
			for (int num = _slots.Count - 1; num >= 0; num--)
			{
				if (!Object.op_Implicit((Object)(object)_slots[num].Item))
				{
					VaultRegistry.ClearHeld(_slots[num].Key);
					_slots.RemoveAt(num);
				}
			}
		}

		private void SpillAll(string reason)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PruneMissing();
				if (_slots.Count == 0)
				{
					return;
				}
				ResolveSpillOrigin(out var origin, out var facing);
				float time = Time.time;
				int num = 0;
				foreach (Slot slot in _slots)
				{
					VaultRegistry.ClearHeld(slot.Key);
					PhysGrabObject item = slot.Item;
					if (Object.op_Implicit((Object)(object)item))
					{
						VaultRegistry.LockIntake(item, time + 2.5f);
						ParkedBody.Free(item);
						ShrinkBridge.Restore(item);
						Vector3 center = origin + facing * SpillOffset(num);
						item.Teleport(PivotFor(item, center, facing), facing);
						Shield(item, 5f, 1f);
						num++;
					}
				}
				_slots.Clear();
				_settleSince.Clear();
				Plugin.Log.LogInfo((object)$"Cart {ViewId}: spilled {num} stored item(s) ({reason}).");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)$"Cart {ViewId}: failed to spill stored items ({reason}): {ex.Message}");
			}
		}

		internal void LeaveContentsAtExtraction()
		{
			if (_ready && RunGate.IsHost && _inExtraction)
			{
				SpillAll("cart rescued from the extraction point");
				UncloakAll();
			}
		}

		private void ResolveSpillOrigin(out Vector3 origin, out Quaternion facing)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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)
			if (_hasDockedPose)
			{
				origin = _dockedCenter;
				facing = YawOnly(_dockedRotation);
				return;
			}
			TruckSafetySpawnPoint instance = TruckSafetySpawnPoint.instance;
			if (Object.op_Implicit((Object)(object)instance))
			{
				origin = ((Component)instance).transform.position;
				facing = YawOnly(((Component)instance).transform.rotation);
			}
			else
			{
				origin = ((Component)this).transform.position;
				facing = Quaternion.identity;
			}
		}

		private static void Shield(PhysGrabObject item, float indestructibleSeconds, float impactMuteSeconds)
		{
			item.OverrideIndestructible(indestructibleSeconds);
			PhysGrabObjectImpactDetector component = ((Component)item).GetComponent<PhysGrabObjectImpactDetector>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.ImpactDisable(impactMuteSeconds);
			}
		}

		private static Vector3 PivotFor(PhysGrabObject item, Vector3 center, Quaternion rotation)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.Scale(item.midPointOffset, ((Component)item).transform.lossyScale);
			return center - rotation * val;
		}

		private static Vector3 SpillOffset(int index)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			int num = index / SpillCellOrder.Length;
			int num2 = SpillCellOrder[index % SpillCellOrder.Length];
			return new Vector3((float)(num2 % 3 - 1) * 0.6f, 0.5f + (float)num * 0.6f, (float)(num2 / 3 - 1) * 0.6f);
		}

		private static Quaternion YawOnly(Quaternion rotation)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			return Quaternion.Euler(0f, ((Quaternion)(ref rotation)).eulerAngles.y, 0f);
		}
	}
	internal sealed class Cloak : MonoBehaviour
	{
		private const float RescanInterval = 2f;

		private readonly List<KeyValuePair<Renderer, bool>> _renderers = new List<KeyValuePair<Renderer, bool>>();

		private readonly List<KeyValuePair<Light, bool>> _lights = new List<KeyValuePair<Light, bool>>();

		private readonly List<KeyValuePair<Collider, bool>> _colliders = new List<KeyValuePair<Collider, bool>>();

		private readonly HashSet<int> _recorded = new HashSet<int>();

		private float _nextRescan;

		internal bool On { get; private set; }

		internal static void Set(PhysGrabObject item, bool hidden)
		{
			Cloak cloak = ((Component)item).GetComponent<Cloak>();
			if (!Object.op_Implicit((Object)(object)cloak))
			{
				if (!hidden)
				{
					return;
				}
				cloak = ((Component)item).gameObject.AddComponent<Cloak>();
			}
			if (hidden)
			{
				cloak.Hide();
			}
			else
			{
				cloak.Show();
			}
		}

		private void Hide()
		{
			if (!On)
			{
				On = true;
				Record();
				_nextRescan = Time.time + 2f;
			}
			Enforce();
		}

		private void Show()
		{
			if (!On)
			{
				return;
			}
			On = false;
			foreach (KeyValuePair<Renderer, bool> renderer in _renderers)
			{
				if (Object.op_Implicit((Object)(object)renderer.Key))
				{
					renderer.Key.forceRenderingOff = renderer.Value;
				}
			}
			foreach (KeyValuePair<Light, bool> light in _lights)
			{
				if (Object.op_Implicit((Object)(object)light.Key))
				{
					((Behaviour)light.Key).enabled = light.Value;
				}
			}
			foreach (KeyValuePair<Collider, bool> collider in _colliders)
			{
				if (Object.op_Implicit((Object)(object)collider.Key))
				{
					collider.Key.enabled = collider.Value;
				}
			}
			_renderers.Clear();
			_lights.Clear();
			_colliders.Clear();
			_recorded.Clear();
		}

		private void LateUpdate()
		{
			if (On)
			{
				if (Time.time >= _nextRescan)
				{
					_nextRescan = Time.time + 2f;
					Record();
				}
				Enforce();
			}
		}

		private void Record()
		{
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (_recorded.Add(((Object)val).GetInstanceID()))
				{
					_renderers.Add(new KeyValuePair<Renderer, bool>(val, val.forceRenderingOff));
				}
			}
			Light[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Light>(true);
			foreach (Light val2 in componentsInChildren2)
			{
				if (_recorded.Add(((Object)val2).GetInstanceID()))
				{
					_lights.Add(new KeyValuePair<Light, bool>(val2, ((Behaviour)val2).enabled));
				}
			}
			Collider[] componentsInChildren3 = ((Component)this).GetComponentsInChildren<Collider>(true);
			foreach (Collider val3 in componentsInChildren3)
			{
				if (_recorded.Add(((Object)val3).GetInstanceID()))
				{
					_colliders.Add(new KeyValuePair<Collider, bool>(val3, val3.enabled));
				}
			}
		}

		private void Enforce()
		{
			foreach (KeyValuePair<Renderer, bool> renderer in _renderers)
			{
				if (Object.op_Implicit((Object)(object)renderer.Key) && !renderer.Key.forceRenderingOff)
				{
					renderer.Key.forceRenderingOff = true;
				}
			}
			foreach (KeyValuePair<Light, bool> light in _lights)
			{
				if (Object.op_Implicit((Object)(object)light.Key) && ((Behaviour)light.Key).enabled)
				{
					((Behaviour)light.Key).enabled = false;
				}
			}
			foreach (KeyValuePair<Collider, bool> collider in _colliders)
			{
				if (Object.op_Implicit((Object)(object)collider.Key) && collider.Key.enabled)
				{
					collider.Key.enabled = false;
				}
			}
		}
	}
	internal static class GameAccess
	{
		private static FieldRef<PhysGrabInCart, List<CartObject>> _cartEntries;

		private static FieldRef<PhysGrabObjectImpactDetector, PhysGrabCart> _detectorCart;

		private static FieldRef<ValuableObject, float> _dollarValue;

		private static FieldRef<ValuableObject, bool> _dollarValueReady;

		private static FieldRef<ItemEquippable, bool> _equipping;

		private static FieldRef<ItemEquippable, bool> _unequipping;

		private static FieldRef<CosmeticWorldObject, bool> _exploding;

		private static FieldRef<PhysGrabObjectImpactDetector, float> _inCartTimer;

		private static FieldRef<Enemy, EnemyHealth> _enemyHealth;

		private static FieldRef<EnemyHealth, int> _enemyHealthCurrent;

		private static FieldRef<EnemyHealth, bool> _enemyDead;

		private static FieldRef<PhysGrabObject, bool> _hostKinematic;

		private static FieldRef<RoundDirector, List<PhysGrabObject>> _allBodies;

		private static FieldInfo _boxClaims;

		internal static bool Ready { get; private set; }

		internal static void Resolve()
		{
			try
			{
				_cartEntries = AccessTools.FieldRefAccess<PhysGrabInCart, List<CartObject>>("inCartObjects");
				_detectorCart = AccessTools.FieldRefAccess<PhysGrabObjectImpactDetector, PhysGrabCart>("currentCart");
				_dollarValue = AccessTools.FieldRefAccess<ValuableObject, float>("dollarValueCurrent");
				Ready = _cartEntries != null && _detectorCart != null && _dollarValue != null;
			}
			catch (Exception ex)
			{
				Ready = false;
				Plugin.Log.LogError((object)("Required game fields could not be bound: " + ex.Message));
			}
			if (!Ready)
			{
				Plugin.Log.LogError((object)"Carts will stay vanilla - the game was probably updated.");
				return;
			}
			_dollarValueReady = Optional<ValuableObject, bool>("dollarValueSet");
			_equipping = Optional<ItemEquippable, bool>("isEquipping");
			_unequipping = Optional<ItemEquippable, bool>("isUnequipping");
			_exploding = Optional<CosmeticWorldObject, bool>("exploding");
			_inCartTimer = Optional<PhysGrabObjectImpactDetector, float>("timerInCart");
			_enemyHealth = Optional<Enemy, EnemyHealth>("Health");
			_enemyHealthCurrent = Optional<EnemyHealth, int>("healthCurrent");
			_enemyDead = Optional<EnemyHealth, bool>("dead");
			_hostKinematic = Optional<PhysGrabObject, bool>("isKinematic");
			_allBodies = Optional<RoundDirector, List<PhysGrabObject>>("physGrabObjects");
			_boxClaims = AccessTools.Field(typeof(ItemValuableBox), "claimedValuables");
		}

		internal static bool KillEnemy(Enemy enemy)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)enemy) || _enemyHealth == null || _enemyHealthCurrent == null || _enemyDead == null)
			{
				return false;
			}
			EnemyHealth val = _enemyHealth.Invoke(enemy);
			if (!Object.op_Implicit((Object)(object)val) || _enemyDead.Invoke(val))
			{
				return false;
			}
			int num = _enemyHealthCurrent.Invoke(val);
			if (num <= 0)
			{
				return false;
			}
			val.Hurt(Math.Max(num, val.health) + 1, Vector3.up);
			return true;
		}

		internal static List<CartObject> CartEntries(PhysGrabInCart zone)
		{
			if (!Object.op_Implicit((Object)(object)zone))
			{
				return null;
			}
			return _cartEntries.Invoke(zone);
		}

		internal static PhysGrabCart CartOf(PhysGrabObjectImpactDetector detector)
		{
			if (!Object.op_Implicit((Object)(object)detector))
			{
				return null;
			}
			return _detectorCart.Invoke(detector);
		}

		internal static int DollarValue(ValuableObject valuable)
		{
			if (!Object.op_Implicit((Object)(object)valuable))
			{
				return 0;
			}
			return (int)_dollarValue.Invoke(valuable);
		}

		internal static bool DollarValueReady(ValuableObject valuable)
		{
			if (_dollarValueReady != null)
			{
				return _dollarValueReady.Invoke(valuable);
			}
			return true;
		}

		internal static bool InEquipTransition(ItemEquippable equip)
		{
			if (_equipping == null || !_equipping.Invoke(equip))
			{
				if (_unequipping != null)
				{
					return _unequipping.Invoke(equip);
				}
				return false;
			}
			return true;
		}

		internal static void HoldInCart(PhysGrabObjectImpactDetector detector, PhysGrabCart cart, float seconds)
		{
			if (Object.op_Implicit((Object)(object)detector) && _inCartTimer != null)
			{
				_detectorCart.Invoke(detector) = cart;
				_inCartTimer.Invoke(detector) = seconds;
			}
		}

		internal static bool? HostKinematic(PhysGrabObject body)
		{
			if (_hostKinematic == null || !Object.op_Implicit((Object)(object)body))
			{
				return null;
			}
			return _hostKinematic.Invoke(body);
		}

		internal static List<PhysGrabObject> AllBodies()
		{
			RoundDirector instance = RoundDirector.instance;
			if (!Object.op_Implicit((Object)(object)instance) || _allBodies == null)
			{
				return null;
			}
			return _allBodies.Invoke(instance);
		}

		internal static bool IsExploding(CosmeticWorldObject cosmetic)
		{
			if (_exploding != null)
			{
				return _exploding.Invoke(cosmetic);
			}
			return false;
		}

		internal static bool IsClaimedByValuableBox(PhysGrabObject item)
		{
			if (_boxClaims == null)
			{
				return false;
			}
			try
			{
				return _boxClaims.GetValue(null) is HashSet<PhysGrabObject> hashSet && hashSet.Contains(item);
			}
			catch (Exception)
			{
				return false;
			}
		}

		private static FieldRef<T, F> Optional<T, F>(string field) where T : class
		{
			try
			{
				return AccessTools.FieldRefAccess<T, F>(field);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Optional field " + typeof(T).Name + "." + field + " not found, skipping that check: " + ex.Message));
				return null;
			}
		}
	}
	internal static class LeaverItems
	{
		private static readonly FieldInfo InstanceNameField = AccessTools.Field(typeof(ItemAttributes), "instanceName");

		private static readonly FieldInfo SteamIdField = AccessTools.Field(typeof(PlayerAvatar), "steamID");

		private static readonly FieldInfo ForceUnequipField = AccessTools.Field(typeof(ItemEquippable), "isForceUnequipping");

		internal static IEnumerator ReleaseAfterLeave()
		{
			yield return (object)new WaitForSeconds(0.5f);
			ReleaseOrphans();
		}

		internal static int ReleaseOrphans()
		{
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.LateJoinLoaded || !ModConfig.ReturnLeaverItems.Value)
			{
				return 0;
			}
			if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient)
			{
				return 0;
			}
			if ((Object)(object)RunManager.instance == (Object)null || SemiFunc.MenuLevel() || SemiFunc.RunIsShop() || SemiFunc.RunIsArena())
			{
				return 0;
			}
			if ((Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated)
			{
				return 0;
			}
			PlayerAvatar val = SemiFunc.PlayerAvatarLocal();
			if ((Object)(object)val == (Object)null || (Object)(object)val.photonView == (Object)null)
			{
				return 0;
			}
			List<string> list = new List<string>();
			ItemEquippable[] array = Object.FindObjectsOfType<ItemEquippable>();
			foreach (ItemEquippable val2 in array)
			{
				if ((Object)(object)val2 == (Object)null || !val2.IsEquipped() || (Object)(object)val2.GetOwnerPlayerAvatar() != (Object)null)
				{
					continue;
				}
				PhotonView component = ((Component)val2).GetComponent<PhotonView>();
				PhysGrabObject component2 = ((Component)val2).GetComponent<PhysGrabObject>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null))
				{
					component.RPC("RPC_UpdateItemState", (RpcTarget)0, new object[3]
					{
						3,
						-1,
						val.photonView.ViewID
					});
					ForceUnequipField?.SetValue(val2, true);
					component2.OverrideDeactivateReset();
					float num = 0.3f * (float)list.Count;
					if (!CartRescue.MoveToTruck(component2, num))
					{
						component2.Teleport(NextToHost(val) + Vector3.up * num, Quaternion.identity);
					}
					ForgetSlotRecord(val2);
					list.Add(((Object)val2).name);
				}
			}
			if (list.Count > 0)
			{
				Plugin.Log.LogInfo((object)("[Rescued] " + string.Join(", ", list) + " -> " + (((Object)(object)TruckSafetySpawnPoint.instance != (Object)null) ? "truck" : "host") + " (owner left)"));
			}
			return list.Count;
		}

		private static void ForgetSlotRecord(ItemEquippable item)
		{
			StatsManager instance = StatsManager.instance;
			ItemAttributes component = ((Component)item).GetComponent<ItemAttributes>();
			string text = (((Object)(object)component != (Object)null) ? (InstanceNameField?.GetValue(component) as string) : null);
			if ((Object)(object)instance == (Object)null || string.IsNullOrEmpty(text) || (Object)(object)GameDirector.instance == (Object)null)
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>();
			foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
			{
				if ((Object)(object)player != (Object)null && SteamIdField?.GetValue(player) is string item2)
				{
					hashSet.Add(item2);
				}
			}
			int hashCode = text.GetHashCode();
			Dictionary<string, int>[] array = new Dictionary<string, int>[3] { instance.playerInventorySpot1, instance.playerInventorySpot2, instance.playerInventorySpot3 };
			for (int i = 0; i < array.Length; i++)
			{
				foreach (KeyValuePair<string, int> item3 in new List<KeyValuePair<string, int>>(array[i]))
				{
					if (item3.Value == hashCode && !hashSet.Contains(item3.Key))
					{
						instance.PlayerInventoryUpdate(item3.Key, "", i, true);
					}
				}
			}
		}

		private static Vector3 NextToHost(PlayerAvatar host)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)host).transform;
			return transform.position + transform.forward * 1f + Vector3.up * 0.5f;
		}
	}
	internal static class ModConfig
	{
		private sealed class Named
		{
			internal ConfigEntryBase Entry;

			internal string Section;

			internal string[] Keys;

			internal string[] Text;
		}

		internal static ConfigEntry<string> Language;

		internal static ConfigEntry<bool> KillEnemiesInCart;

		internal static ConfigEntry<bool> RescueCarts;

		internal static ConfigEntry<bool> ReturnLeaverItems;

		private const string LanguageSection = "Language / 언어 / 言語";

		private const string Cart = "Cart";

		private const string Protection = "Protection";

		private const string OldCart = "Cart / 카트";

		private const string OldProtection = "Protection / 보호";

		private static readonly string[] Languages = new string[3] { "English", "한국어", "日本語" };

		private static ConfigFile _file;

		private static Dictionary<ConfigDefinition, string> _saved;

		private static int _lang;

		private static readonly List<Named> Localized = new List<Named>();

		private static readonly PropertyInfo EntriesProperty = typeof(ConfigFile).GetProperty("Entries", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo DefinitionField = typeof(ConfigEntryBase).GetField("<Definition>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo DescriptionField = typeof(ConfigEntryBase).GetField("<Description>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);

		internal static void Bind(ConfigFile cfg)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			_file = cfg;
			Localized.Clear();
			_saved = typeof(ConfigFile).GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(cfg) as Dictionary<ConfigDefinition, string>;
			bool saveOnConfigSet = cfg.SaveOnConfigSet;
			cfg.SaveOnConfigSet = false;
			try
			{
				Language = cfg.Bind<string>("Language / 언어 / 言語", "Language", Languages[0], new ConfigDescription("Language of these settings. Applied at once; reopen the REPOConfig mod list to see it. / 설정 언어입니다. 바로 적용되며, REPOConfig 모드 목록을 다시 열면 보입니다. / 設定の言語です。すぐに反映され、REPOConfigのMOD一覧を開き直すと表示されます。", (AcceptableValueBase)(object)new AcceptableValueList<string>(Languages), Array.Empty<object>()));
				_lang = Math.Max(0, Array.IndexOf(Languages, Language.Value));
				KillEnemiesInCart = Bind("Cart", L("Kill Enemies In Cart", "카트 몬스터 즉사", "カート内の敵を即死"), value: true, L("Enemies that get into a cart die instantly. Host only, applied live.", "카트에 들어온 몬스터를 즉사시킵니다. 호스트 설정, 즉시 적용.", "カートに入った敵を即死させます。ホスト設定、即時反映。"), Old("Cart / 카트", "KillEnemiesInCart"));
				RescueCarts = Bind("Protection", L("Rescue Carts", "카트 파괴 방지", "カート破壊防止"), value: true, L("Carts and vehicles that would be destroyed or lost (extraction point, pit, water, falling out of the map) go back to the truck. Not in the shop. Host only. RepoLateJoin's setting wins if installed.", "추출구·구덩이·물·맵 밖 추락 등으로 부서지거나 잃어버릴 카트와 탈것을 트럭으로 되돌립니다. 상점 제외. 호스트 설정. RepoLateJoin이 있으면 그쪽 설정을 따릅니다.", "抽出口・穴・水・マップ外への落下などで壊れたり失われたりするカートと乗り物をトラックに戻します。ショップを除く。ホスト設定。RepoLateJoinがあればそちらの設定に従います。"), Old("Protection / 보호", "RescueCarts"));
				ReturnLeaverItems = Bind("Protection", L("Return Leaver Items", "나간 플레이어 아이템 회수", "退出者のアイテムを回収"), value: true, L("Items in the inventory of a player who leaves are dropped in the truck instead of staying invisible. Not in the shop. Host only. RepoLateJoin's setting wins if installed.", "나간 플레이어의 인벤토리 아이템을 보이지 않게 남기지 않고 트럭에 떨어뜨립니다. 상점 제외. 호스트 설정. RepoLateJoin이 있으면 그쪽 설정을 따릅니다.", "退出したプレイヤーのインベントリのアイテムを、見えないまま残さずトラックに落とします。ショップを除く。ホスト設定。RepoLateJoinがあればそちらの設定に従います。"), Old("Protection / 보호", "ReturnLeaverItems"));
			}
			finally
			{
				cfg.SaveOnConfigSet = saveOnConfigSet;
			}
			cfg.Save();
			Language.SettingChanged += delegate
			{
				ApplyLanguage();
			};
		}

		private static void ApplyLanguage()
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			int num = Math.Max(0, Array.IndexOf(Languages, Language.Value));
			Dictionary<ConfigDefinition, ConfigEntryBase> dictionary = EntriesProperty?.GetValue(_file) as Dictionary<ConfigDefinition, ConfigEntryBase>;
			if (num == _lang || dictionary == null || DefinitionField == null || DescriptionField == null)
			{
				return;
			}
			_lang = num;
			foreach (Named item in Localized)
			{
				ConfigDefinition val = new ConfigDefinition(item.Section, item.Keys[num]);
				ConfigDescription description = item.Entry.Description;
				dictionary.Remove(item.Entry.Definition);
				DefinitionField.SetValue(item.Entry, val);
				DescriptionField.SetValue(item.Entry, (object?)new ConfigDescription(item.Text[num], description.AcceptableValues, description.Tags));
				dictionary[val] = item.Entry;
			}
			_file.Save();
			Plugin.Log.LogInfo((object)("Settings language: " + Languages[num] + "."));
		}

		private static string[] L(string english, string korean, string japanese)
		{
			return new string[3] { english, korean, japanese };
		}

		private static ConfigDefinition[] Old(string section, params string[] keys)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			ConfigDefinition[] array = (ConfigDefinition[])(object)new ConfigDefinition[keys.Length];
			for (int i = 0; i < keys.Length; i++)
			{
				array[i] = new ConfigDefinition(section, keys[i]);
			}
			return array;
		}

		private static ConfigEntry<T> Bind<T>(string section, string[] keys, T value, string[] text, params ConfigDefinition[] before)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			ConfigDefinition val = new ConfigDefinition(section, keys[_lang]);
			bool flag = _saved != null && _saved.ContainsKey(val);
			List<ConfigDefinition> list = new List<ConfigDefinition>(Old(section, keys));
			list.AddRange(before);
			string text2 = null;
			foreach (ConfigDefinition item in list)
			{
				if (!item.Equals(val) && _saved != null && _saved.TryGetValue(item, out var value2))
				{
					text2 = text2 ?? value2;
					_saved.Remove(item);
				}
			}
			ConfigEntry<T> val2 = _file.Bind<T>(val, value, new ConfigDescription(text[_lang], (AcceptableValueBase)null, Array.Empty<object>()));
			if (!flag && text2 != null)
			{
				((ConfigEntryBase)val2).SetSerializedValue(text2);
			}
			Localized.Add(new Named
			{
				Entry = (ConfigEntryBase)(object)val2,
				Section = section,
				Keys = keys,
				Text = text
			});
			return val2;
		}
	}
	internal sealed class ParkedBody : MonoBehaviour
	{
		private PhysGrabObject _body;

		private RigidbodyInterpolation _interpolation;

		internal bool Holding { get; private set; }

		private Rigidbody Body
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)_body))
				{
					_body = ((Component)this).GetComponent<PhysGrabObject>();
				}
				if (!Object.op_Implicit((Object)(object)_body))
				{
					return null;
				}
				return _body.rb;
			}
		}

		internal static void Hold(PhysGrabObject item)
		{
			ParkedBody parkedBody = ((Component)item).GetComponent<ParkedBody>();
			if (!Object.op_Implicit((Object)(object)parkedBody))
			{
				parkedBody = ((Component)item).gameObject.AddComponent<ParkedBody>();
			}
			parkedBody.Engage();
		}

		internal static void Free(PhysGrabObject item)
		{
			ParkedBody component = ((Component)item).GetComponent<ParkedBody>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.Release();
			}
		}

		private void Engage()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!Holding)
			{
				Rigidbody body = Body;
				if (Object.op_Implicit((Object)(object)body))
				{
					_interpolation = body.interpolation;
					Freeze(body);
					body.interpolation = (RigidbodyInterpolation)0;
					Holding = true;
				}
			}
		}

		private void Release()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (Holding)
			{
				Holding = false;
				Rigidbody body = Body;
				if (Object.op_Implicit((Object)(object)body))
				{
					body.interpolation = _interpolation;
					body.isKinematic = false;
					body.velocity = Vector3.zero;
					body.angularVelocity = Vector3.zero;
					body.WakeUp();
				}
			}
		}

		private void LateUpdate()
		{
			if (Holding)
			{
				Rigidbody body = Body;
				if (Object.op_Implicit((Object)(object)body) && !body.isKinematic)
				{
					Freeze(body);
				}
			}
		}

		private static void Freeze(Rigidbody rb)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!rb.isKinematic)
			{
				rb.velocity = Vector3.zero;
				rb.angularVelocity = Vector3.zero;
			}
			rb.isKinematic = true;
		}
	}
	internal static class PatchInstaller
	{
		internal static void InstallAll(Harmony harmony)
		{
			if (!GameAccess.Ready)
			{
				Plugin.Log.LogError((object)"Game access is not ready, no patches installed.");
				return;
			}
			Apply(harmony, "Pocket Dimension Cart host value (ValueScreen.UpdateValue)", AccessTools.Method(typeof(ValueScreen), "UpdateValue", (Type[])null, (Type[])null), Method(typeof(CartScreenTotal), "Prefix"));
			Apply(harmony, "Cart vault attach (PhysGrabCart.Start)", AccessTools.Method(typeof(PhysGrabCart), "Start", (Type[])null, (Type[])null), null, Method(typeof(CartSpawnHook), "Postfix"));
			Apply(harmony, "Rescue carts (PhysGrabObjectImpactDetector.DestroyObject)", AccessTools.Method(typeof(PhysGrabObjectImpactDetector), "DestroyObject", (Type[])null, (Type[])null), Method(typeof(CartRescuePatch), "Prefix"));
			Apply(harmony, "Return leaver items (NetworkManager.OnPlayerLeftRoom)", AccessTools.Method(typeof(NetworkManager), "OnPlayerLeftRoom", (Type[])null, (Type[])null), null, Method(typeof(PlayerLeftHook), "Postfix"));
		}

		private static bool Apply(Harmony harmony, string label, MethodBase target, HarmonyMethod prefix = null, HarmonyMethod postfix = null)
		{
			if (target == null)
			{
				Plugin.Log.LogWarning((object)("Target not found, skipping - " + label));
				return false;
			}
			try
			{
				harmony.Patch(target, prefix, postfix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)("Installed - " + label));
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to install - " + label + ": " + ex.Message));
				return false;
			}
		}

		private static HarmonyMethod Method(Type type, string name)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(type, name, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				throw new InvalidOperationException("Patch method not found: " + type.Name + "." + name);
			}
			return new HarmonyMethod(methodInfo);
		}
	}
	internal static class RunGate
	{
		private static int _frame = -1;

		private static bool _runLevel;

		private static bool _generated;

		private static bool _host;

		private static bool _playing;

		internal static bool IsRunLevel
		{
			get
			{
				Refresh();
				return _runLevel;
			}
		}

		internal static bool InRunLevel
		{
			get
			{
				Refresh();
				if (_runLevel)
				{
					return _generated;
				}
				return false;
			}
		}

		internal static bool IsHost
		{
			get
			{
				Refresh();
				return _host;
			}
		}

		internal static bool Playing
		{
			get
			{
				Refresh();
				if (_runLevel && _generated)
				{
					return _playing;
				}
				return false;
			}
		}

		private static void Refresh()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Invalid comparison between Unknown and I4
			int frameCount = Time.frameCount;
			if (frameCount == _frame)
			{
				return;
			}
			_frame = frameCount;
			_runLevel = false;
			_generated = false;
			_host = false;
			_playing = false;
			try
			{
				if (!((Object)(object)RunManager.instance == (Object)null) && !((Object)(object)RunManager.instance.levelCurrent == (Object)null) && !SemiFunc.MenuLevel() && SemiFunc.RunIsLevel())
				{
					_runLevel = true;
					_generated = (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated;
					_host = SemiFunc.IsMasterClientOrSingleplayer();
					_playing = (Object)(object)GameDirector.instance != (Object)null && (int)GameDirector.instance.currentState == 2;
				}
			}
			catch (Exception)
			{
				_runLevel = false;
				_generated = false;
				_host = false;
				_playing = false;
			}
		}
	}
	internal static class ShrinkBridge
	{
		internal const string ScalerCoreGuid = "Vippy.ScalerCore";

		private static readonly bool Present = Chainloader.PluginInfos.ContainsKey("Vippy.ScalerCore");

		internal static void Shrink(PhysGrabObject item)
		{
			if (!Present)
			{
				return;
			}
			try
			{
				ScalerCoreCalls.Shrink(((Component)item).gameObject);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("ScalerCore shrink failed on '" + ((Object)item).name + "': " + ex.Message));
			}
		}

		internal static void Restore(PhysGrabObject item)
		{
			if (!Present)
			{
				return;
			}
			try
			{
				ScalerCoreCalls.Restore(((Component)item).gameObject);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("ScalerCore restore failed on '" + ((Object)item).name + "': " + ex.Message));
			}
		}
	}
	internal static class ScalerCoreCalls
	{
		private const float VaultFactor = 0.0001f;

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void Shrink(GameObject target)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			ScaleController controller = ScaleManager.GetController(target);
			if (!((Object)(object)controller == (Object)null))
			{
				ScaleOptions val = ScaleOptions.Default;
				val.Factor = 0.0001f;
				val.Speed = 0.5f;
				val.RestoreSpeed = 0.2f;
				val.Duration = 0f;
				val.AllowedTargets = (ScaleTargets)15;
				val.SuppressValueDropExpand = true;
				val.SuppressImpactFlash = true;
				val.SuppressCameraShake = true;
				val.IgnoreBonkExpand = true;
				val.RejectExternalApply = true;
				if (controller.IsScaled && Mathf.Approximately(controller.CurrentOptions.Factor, 0.0001f))
				{
					ScaleManager.ForceUpdateOptions(target, val);
				}
				else
				{
					ScaleManager.ForceApply(target, val);
				}
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void Restore(GameObject target)
		{
			if (ScaleManager.IsScaled(target))
			{
				ScaleManager.ForceRestore(target);
			}
		}
	}
	internal sealed class ValueCarrier
	{
		private const float Scale = 0.001f;

		private const float SettleSeconds = 1f;

		private const float SyncInterval = 0.25f;

		private const float ShieldInterval = 0.5f;

		private const float ShieldSeconds = 1.5f;

		private PhysGrabObject _body;

		private ValuableObject _valuable;

		private PhotonView _view;

		private float _spawnedAt;

		private float _nextSync;

		private float _nextShield;

		private int _sent = -1;

		private bool _spawnFailed;

		internal PhysGrabObject Body => _body;

		internal void Tick(PhysGrabCart cart, int value, Vector3 park, float now)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_body))
			{
				if (value > 0 && !_spawnFailed)
				{
					Spawn(park, now);
				}
				return;
			}
			ParkedBody.Hold(_body);
			if (now >= _nextShield)
			{
				_nextShield = now + 0.5f;
				_body.OverrideIndestructible(1.5f);
				PhysGrabObjectImpactDetector component = ((Component)_body).GetComponent<PhysGrabObjectImpactDetector>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.ImpactDisable(1.5f);
				}
				GameAccess.HoldInCart(component, cart, 1.5f);
			}
			if (now >= _nextSync && now - _spawnedAt >= 1f)
			{
				_nextSync = now + 0.25f;
				if (value != _sent)
				{
					Send(value);
				}
			}
		}

		internal bool IsReady(float now)
		{
			if (Object.op_Implicit((Object)(object)_body) && now - _spawnedAt >= 1f)
			{
				return _sent >= 0;
			}
			return false;
		}

		internal void Place(Vector3 pivot, Quaternion rotation)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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)
			//IL_004a: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_body))
			{
				return;
			}
			Transform transform = ((Component)_body).transform;
			Vector3 val = transform.position - pivot;
			if (!(((Vector3)(ref val)).sqrMagnitude < 1E-06f) || !(Quaternion.Angle(transform.rotation, rotation) < 0.05f))
			{
				transform.SetPositionAndRotation(pivot, rotation);
				Rigidbody rb = _body.rb;
				if (Object.op_Implicit((Object)(object)rb))
				{
					rb.position = pivot;
					rb.rotation = rotation;
				}
			}
		}

		internal void Destroy()
		{
			if (Object.op_Implicit((Object)(object)_body))
			{
				_body.DestroyPhysGrabObject();
			}
			_body = null;
		}

		private void Spawn(Vector3 park, float now)
		{
			//IL_0044: 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_0053: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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)
			//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_00db: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = (Object.op_Implicit((Object)(object)AssetManager.instance) ? AssetManager.instance.surplusValuableSmall : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				_spawnFailed = true;
				Plugin.Log.LogError((object)"Surplus valuable prefab not found - cart screens cannot show stored value.");
				return;
			}
			VaultYard.EnsureFloor();
			Vector3 val2 = val.transform.localScale * 0.001f;
			GameObject val3 = (SemiFunc.IsMultiplayer() ? PhotonNetwork.InstantiateRoomObject("Valuables/" + ((Object)val).name, park, Quaternion.identity, (byte)0, new object[3] { val2.x, val2.y, val2.z }) : Object.Instantiate<GameObject>(val, park, Quaternion.identity));
			if (!Object.op_Implicit((Object)(object)val3))
			{
				_spawnFailed = true;
				Plugin.Log.LogError((object)"Could not spawn the cart value carrier.");
				return;
			}
			val3.transform.localScale = val2;
			_body = val3.GetComponent<PhysGrabObject>();
			_valuable = val3.GetComponent<ValuableObject>();
			_view = val3.GetComponent<PhotonView>();
			_spawnedAt = now;
			_sent = -1;
			if (!Object.op_Implicit((Object)(object)_body) || !Object.op_Implicit((Object)(object)_valuable))
			{
				_spawnFailed = true;
				Plugin.Log.LogError((object)"The cart value carrier prefab is not a valuable.");
				Destroy();
			}
		}

		private void Send(int value)
		{
			//IL_0050: 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)
			if (!GameAccess.DollarValueReady(_valuable))
			{
				return;
			}
			if (SemiFunc.IsMultiplayer())
			{
				if (!Object.op_Implicit((Object)(object)_view))
				{
					return;
				}
				_view.RPC("DollarValueSetRPC", (RpcTarget)0, new object[1] { (float)value });
			}
			else
			{
				_valuable.DollarValueSetRPC((float)value, default(PhotonMessageInfo));
			}
			_sent = value;
		}
	}
	internal static class VaultRegistry
	{
		private static readonly Dictionary<int, CartVault> ByScreen = new Dictionary<int, CartVault>();

		private static readonly Dictionary<int, CartVault> Holders = new Dictionary<int, CartVault>();

		private static readonly Dictionary<int, float> IntakeLocks = new Dictionary<int, float>();

		private static int _nextYardIndex;

		internal static void Register(CartVault vault, ValueScreen screen)
		{
			if (Object.op_Implicit((Object)(object)screen))
			{
				ByScreen[((Object)screen).GetInstanceID()] = vault;
			}
		}

		internal static void Unregister(CartVault vault)
		{
			RemoveValue(ByScreen, vault);
			RemoveValue(Holders, vault);
		}

		internal static CartVault FindByScreen(ValueScreen screen)
		{
			if (!Object.op_Implicit((Object)(object)screen) || !ByScreen.TryGetValue(((Object)screen).GetInstanceID(), out var value))
			{
				return null;
			}
			return value;
		}

		internal static int NextYardIndex()
		{
			return _nextYardIndex++;
		}

		internal static bool IsHeld(PhysGrabObject item)
		{
			return Holders.ContainsKey(((Object)item).GetInstanceID());
		}

		internal static void MarkHeld(PhysGrabObject item, CartVault vault)
		{
			Holders[((Object)item).GetInstanceID()] = vault;
		}

		internal static void ClearHeld(int itemKey)
		{
			Holders.Remove(itemKey);
		}

		internal static bool IsIntakeLocked(PhysGrabObject item, float now)
		{
			int instanceID = ((Object)item).GetInstanceID();
			if (!IntakeLocks.TryGetValue(instanceID, out var value))
			{
				return false;
			}
			if (now < value)
			{
				return true;
			}
			IntakeLocks.Remove(instanceID);
			return false;
		}

		internal static void LockIntake(PhysGrabObject item, float until)
		{
			IntakeLocks[((Object)item).GetInstanceID()] = until;
		}

		internal static void Reset()
		{
			ByScreen.Clear();
			Holders.Clear();
			IntakeLocks.Clear();
			_nextYardIndex = 0;
		}

		private static void RemoveValue(Dictionary<int, CartVault> map, CartVault vault)
		{
			List<int> list = null;
			foreach (KeyValuePair<int, CartVault> item in map)
			{
				if (item.Value == vault)
				{
					if (list == null)
					{
						list = new List<int>();
					}
					list.Add(item.Key);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (int item2 in list)
			{
				map.Remove(item2);
			}
		}
	}
	internal static class VaultYard
	{
		private static readonly Vector3 Origin = new Vector3(-6000f, 2500f, -6000f);

		private const float CellSize = 4f;

		private const int Columns = 16;

		private const float CartStride = 80f;

		private const float FloorSize = 2400f;

		private const float FloorThickness = 2f;

		private static GameObject _floor;

		internal static void EnsureFloor()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_floor))
			{
				_floor = new GameObject("PocketCart Vault Floor");
				_floor.transform.position = Origin + new Vector3(1000f, -1f, 1000f);
				_floor.AddComponent<BoxCollider>().size = new Vector3(2400f, 2f, 2400f);
			}
		}

		internal static Vector3 CellFloor(int yardIndex, int cell)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			return Origin + new Vector3((float)yardIndex * 80f + (float)(cell % 16) * 4f, 0f, (float)(cell / 16) * 4f);
		}

		internal static Vector3 CarrierPark(int yardIndex)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			return Origin + new Vector3((float)yardIndex * 80f, 0.5f, -8f);
		}
	}
}