Decompiled source of PocketCart v1.0.4

BepInEx/plugins/RepoPocketCart.dll

Decompiled 4 days ago
using System;
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.Logging;
using ExitGames.Client.Photon;
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("1.0.4.0")]
[assembly: AssemblyInformationalVersion("1.0.4")]
[assembly: AssemblyProduct("Pocket Cart")]
[assembly: AssemblyTitle("RepoPocketCart")]
[assembly: AssemblyVersion("1.0.4.0")]
namespace PocketCart
{
	[BepInPlugin("com.sunwu.pocket_cart", "Pocket Cart", "1.0.4")]
	[BepInIncompatibility("empress.repo.pocketdimensioncart")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			GameAccess.Resolve();
			PatchInstaller.InstallAll(new Harmony("com.sunwu.pocket_cart"));
			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 1.0.4 ready - cart contents are folded into the cart (host-authoritative).");
		}
	}
	internal static class PluginInfo
	{
		internal const string Guid = "com.sunwu.pocket_cart";

		internal const string Name = "Pocket Cart";

		internal const string Version = "1.0.4";

		internal const string ReplacedGuid = "empress.repo.pocketdimensioncart";
	}
}
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) && cartVault.Count != 0)
				{
					newValue += cartVault.HiddenValuableTotal();
				}
			}
			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>();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not attach a vault to cart '" + ((Object)__instance).name + "': " + ex.Message));
			}
		}
	}
}
namespace PocketCart.Core
{
	internal sealed class CartVault : MonoBehaviour
	{
		private struct Slot
		{
			public PhysGrabObject Item;

			public int Key;

			public int ViewId;

			public Quaternion Rest;
		}

		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 GrabKickInterval = 0.25f;

		private const float GrabKickLockSeconds = 0.4f;

		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 MirrorRetryInterval = 0.5f;

		private const float PinDistanceSqr = 1E-06f;

		private const float PinAngle = 0.05f;

		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 HashSet<int> _mirrorViews = new HashSet<int>();

		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 PhysGrabCart _cart;

		private PhysGrabObject _cartBody;

		private ItemEquippable _equip;

		private Transform _bay;

		private bool _ready;

		private bool _dirty;

		private bool _hasDockedPose;

		private Vector3 _dockedCenter;

		private Quaternion _dockedRotation = Quaternion.identity;

		private float _nextIntakeScan;

		private float _nextShield;

		private float _nextGrabKick;

		private float _nextMirrorRetry;

		internal int ViewId { get; private set; }

		internal int Count => _slots.Count;

		private void Start()
		{
			_cart = ((Component)this).GetComponent<PhysGrabCart>();
			_cartBody = ((Component)this).GetComponent<PhysGrabObject>();
			_equip = ((Component)this).GetComponent<ItemEquippable>();
			_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);
				return;
			}
			_ready = true;
			VaultRegistry.Register(this, _cart.valueScreen);
			if (!SemiFunc.IsMultiplayer())
			{
				return;
			}
			VaultNet.EnsureListening();
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				int[] array = VaultRegistry.TakePendingMirror(ViewId);
				if (array != null)
				{
					ApplyMirror(array);
				}
				VaultNet.RequestSnapshot();
			}
		}

		private void Update()
		{
			if (_ready && RunGate.InRunLevel)
			{
				if (RunGate.IsHost)
				{
					HostTick(Time.time);
				}
				else
				{
					MirrorTick(Time.time);
				}
			}
		}

		private void LateUpdate()
		{
			if (_ready && _slots.Count != 0 && RunGate.IsHost)
			{
				PinContents();
			}
		}

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

		private void OnDestroy()
		{
			if (!_ready)
			{
				return;
			}
			_ready = false;
			if (RunGate.IsHost)
			{
				if (RunGate.Playing)
				{
					SpillAll("cart destroyed");
				}
			}
			else
			{
				ReleaseMirror();
			}
			VaultRegistry.Unregister(this);
		}

		internal int HiddenValuableTotal()
		{
			int num = 0;
			for (int i = 0; i < _slots.Count; i++)
			{
				PhysGrabObject item = _slots[i].Item;
				if (!Object.op_Implicit((Object)(object)item))
				{
					continue;
				}
				StashMask component = ((Component)item).GetComponent<StashMask>();
				if (Object.op_Implicit((Object)(object)component) && component.Engaged)
				{
					ValuableObject component2 = ((Component)item).GetComponent<ValuableObject>();
					if (Object.op_Implicit((Object)(object)component2))
					{
						num += GameAccess.DollarValue(component2);
					}
				}
			}
			return num;
		}

		internal int[] ExportViewIds()
		{
			List<int> list = new List<int>(_slots.Count);
			foreach (Slot slot in _slots)
			{
				if (Object.op_Implicit((Object)(object)slot.Item) && slot.ViewId != 0)
				{
					list.Add(slot.ViewId);
				}
			}
			return list.ToArray();
		}

		internal void ApplyMirror(int[] itemViewIds)
		{
			if (!_ready || RunGate.IsHost)
			{
				return;
			}
			_mirrorViews.Clear();
			if (itemViewIds != null)
			{
				foreach (int num in itemViewIds)
				{
					if (num != 0)
					{
						_mirrorViews.Add(num);
					}
				}
			}
			for (int num2 = _slots.Count - 1; num2 >= 0; num2--)
			{
				Slot slot = _slots[num2];
				if (!Object.op_Implicit((Object)(object)slot.Item) || !_mirrorViews.Contains(slot.ViewId))
				{
					if (Object.op_Implicit((Object)(object)slot.Item))
					{
						Unmask(slot.Item, thawPhysics: false);
					}
					_slots.RemoveAt(num2);
				}
			}
			ResolveMirror();
		}

		private void HostTick(float now)
		{
			//IL_0020: 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_0031: 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)
			if (PruneMissing())
			{
				_dirty = true;
			}
			bool flag = IsDocked();
			if (flag)
			{
				_dockedCenter = _bay.position;
				_dockedRotation = _bay.rotation;
				_hasDockedPose = true;
			}
			if (_slots.Count > 0)
			{
				if (now >= _nextGrabKick)
				{
					_nextGrabKick = now + 0.25f;
					KickGrabbers();
				}
				if (now >= _nextShield)
				{
					_nextShield = now + 0.5f;
					foreach (Slot slot in _slots)
					{
						if (Object.op_Implicit((Object)(object)slot.Item))
						{
							Shield(slot.Item, 1.5f, 1.5f);
							GameAccess.HoldInCart(((Component)slot.Item).GetComponent<PhysGrabObjectImpactDetector>(), _cart, 1.5f);
							NoisyLoot.Hush(slot.Item);
						}
					}
				}
			}
			if (now >= _nextIntakeScan)
			{
				_nextIntakeScan = now + 0.1f;
				if (flag)
				{
					ScanIntake(now);
				}
				else
				{
					_settleSince.Clear();
				}
			}
			if (_dirty)
			{
				_dirty = false;
				VaultNet.PublishCart(this, 0);
			}
		}

		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 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 (!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 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_002a: 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_006d: 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_0099: 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)
			//IL_00b2: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			StashMask stashMask = ((Component)item).GetComponent<StashMask>();
			if (!Object.op_Implicit((Object)(object)stashMask))
			{
				stashMask = ((Component)item).gameObject.AddComponent<StashMask>();
			}
			stashMask.Engage(freezePhysics: true);
			PhotonView component = ((Component)item).GetComponent<PhotonView>();
			Quaternion val = NoisyLoot.RestOffset(item);
			_slots.Add(new Slot
			{
				Item = item,
				Key = ((Object)item).GetInstanceID(),
				ViewId = (Object.op_Implicit((Object)(object)component) ? component.ViewID : 0),
				Rest = val
			});
			VaultRegistry.MarkHeld(item, this);
			_settleSince.Remove(((Object)item).GetInstanceID());
			Quaternion val2 = YawOnly(_bay.rotation) * val;
			item.Teleport(PivotFor(item, _bay.position, val2), val2);
			Shield(item, 1.5f, 1.5f);
			GameAccess.HoldInCart(((Component)item).GetComponent<PhysGrabObjectImpactDetector>(), _cart, 1.5f);
			ShrinkBridge.Shrink(item);
			_dirty = true;
		}

		private void PinContents()
		{
			//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_0041: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_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_006f: 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)
			//IL_0076: 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_00a2: 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_008d: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = _bay.position;
			Quaternion val = YawOnly(_bay.rotation);
			for (int i = 0; i < _slots.Count; i++)
			{
				PhysGrabObject item = _slots[i].Item;
				if (!Object.op_Implicit((Object)(object)item))
				{
					continue;
				}
				Quaternion val2 = val * _slots[i].Rest;
				Vector3 val3 = PivotFor(item, position, val2);
				Transform transform = ((Component)item).transform;
				Vector3 val4 = transform.position - val3;
				if (!(((Vector3)(ref val4)).sqrMagnitude < 1E-06f) || !(Quaternion.Angle(transform.rotation, val2) < 0.05f))
				{
					transform.SetPositionAndRotation(val3, val2);
					Rigidbody rb = item.rb;
					if (Object.op_Implicit((Object)(object)rb))
					{
						rb.position = val3;
						rb.rotation = val2;
					}
				}
			}
		}

		private void KickGrabbers()
		{
			foreach (Slot slot in _slots)
			{
				PhysGrabObject item = slot.Item;
				if (!Object.op_Implicit((Object)(object)item) || item.playerGrabbing.Count == 0)
				{
					continue;
				}
				PhysGrabber[] array = item.playerGrabbing.ToArray();
				foreach (PhysGrabber val in array)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						val.OverrideGrabRelease(slot.ViewId, 0.4f);
					}
				}
			}
		}

		private bool PruneMissing()
		{
			bool result = false;
			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);
					result = true;
				}
			}
			return result;
		}

		private void SpillAll(string reason)
		{
			//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_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_008b: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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);
						Unmask(item, thawPhysics: true);
						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();
				VaultNet.PublishCart(this, 0);
				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}");
			}
		}

		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 void MirrorTick(float now)
		{
			PruneMissing();
			if (_mirrorViews.Count > _slots.Count && now >= _nextMirrorRetry)
			{
				_nextMirrorRetry = now + 0.5f;
				ResolveMirror();
			}
		}

		private void ResolveMirror()
		{
			foreach (int mirrorView in _mirrorViews)
			{
				if (HasView(mirrorView))
				{
					continue;
				}
				PhotonView val = PhotonView.Find(mirrorView);
				PhysGrabObject val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<PhysGrabObject>() : null);
				if (Object.op_Implicit((Object)(object)val2))
				{
					StashMask stashMask = ((Component)val2).GetComponent<StashMask>();
					if (!Object.op_Implicit((Object)(object)stashMask))
					{
						stashMask = ((Component)val2).gameObject.AddComponent<StashMask>();
					}
					stashMask.Engage(freezePhysics: false);
					_slots.Add(new Slot
					{
						Item = val2,
						Key = ((Object)val2).GetInstanceID(),
						ViewId = mirrorView
					});
				}
			}
		}

		private void ReleaseMirror()
		{
			foreach (Slot slot in _slots)
			{
				if (Object.op_Implicit((Object)(object)slot.Item))
				{
					Unmask(slot.Item, thawPhysics: false);
				}
			}
			_slots.Clear();
			_mirrorViews.Clear();
		}

		private bool HasView(int viewId)
		{
			foreach (Slot slot in _slots)
			{
				if (slot.ViewId == viewId)
				{
					return true;
				}
			}
			return false;
		}

		private static void Unmask(PhysGrabObject item, bool thawPhysics)
		{
			StashMask component = ((Component)item).GetComponent<StashMask>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.Disengage(thawPhysics);
			}
		}

		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 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 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");
			_boxClaims = AccessTools.Field(typeof(ItemValuableBox), "claimedValuables");
		}

		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 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 NoisyLoot
	{
		internal static Quaternion RestOffset(PhysGrabObject item)
		{
			//IL_0047: 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_0027: 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_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)
			BabyHeadValuable component = ((Component)item).GetComponent<BabyHeadValuable>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.head))
			{
				return Quaternion.FromToRotation(Quaternion.Inverse(((Component)item).transform.rotation) * component.head.up, Vector3.forward);
			}
			return Quaternion.identity;
		}

		internal static void Hush(PhysGrabObject item)
		{
			PhoneValuable component = ((Component)item).GetComponent<PhoneValuable>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.PickUp();
			}
		}
	}
	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.");
			}
			else if (!Apply(harmony, "Cart screen total (ValueScreen.UpdateValue)", AccessTools.Method(typeof(ValueScreen), "UpdateValue", (Type[])null, (Type[])null), Method(typeof(CartScreenTotal), "Prefix")))
			{
				Plugin.Log.LogError((object)"Cart screen patch failed, so carts are left vanilla.");
			}
			else
			{
				Apply(harmony, "Cart vault attach (PhysGrabCart.Start)", AccessTools.Method(typeof(PhysGrabCart), "Start", (Type[])null, (Type[])null), null, Method(typeof(CartSpawnHook), "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.01f;

		[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.01f;
				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.01f))
				{
					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 StashMask : MonoBehaviour
	{
		private struct Saved<T> where T : Component
		{
			public T Part;

			public bool State;
		}

		private const float RescanInterval = 2f;

		private readonly List<Saved<Collider>> _colliders = new List<Saved<Collider>>();

		private readonly List<Saved<Renderer>> _renderers = new List<Saved<Renderer>>();

		private readonly List<Saved<Light>> _lights = new List<Saved<Light>>();

		private readonly List<Saved<PhysGrabObjectComponentInsideBoxChecker>> _scanners = new List<Saved<PhysGrabObjectComponentInsideBoxChecker>>();

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

		private PhysGrabObject _body;

		private bool _frozen;

		private bool _wasKinematic;

		private RigidbodyInterpolation _interpolation;

		private float _nextRescan;

		internal bool Engaged { get; private set; }

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

		internal void Engage(bool freezePhysics)
		{
			if (!Engaged)
			{
				Engaged = true;
				Record();
				_nextRescan = Time.time + 2f;
			}
			if (freezePhysics && !_frozen)
			{
				Freeze();
			}
			Enforce();
		}

		internal void Disengage(bool thawPhysics)
		{
			if (!Engaged)
			{
				return;
			}
			Engaged = false;
			foreach (Saved<Collider> collider in _colliders)
			{
				if (Object.op_Implicit((Object)(object)collider.Part))
				{
					collider.Part.enabled = collider.State;
				}
			}
			foreach (Saved<Renderer> renderer in _renderers)
			{
				if (Object.op_Implicit((Object)(object)renderer.Part))
				{
					renderer.Part.forceRenderingOff = renderer.State;
				}
			}
			foreach (Saved<Light> light in _lights)
			{
				if (Object.op_Implicit((Object)(object)light.Part))
				{
					((Behaviour)light.Part).enabled = light.State;
				}
			}
			foreach (Saved<PhysGrabObjectComponentInsideBoxChecker> scanner in _scanners)
			{
				if (Object.op_Implicit((Object)(object)scanner.Part))
				{
					((Behaviour)scanner.Part).enabled = scanner.State;
				}
			}
			_colliders.Clear();
			_renderers.Clear();
			_lights.Clear();
			_scanners.Clear();
			_recorded.Clear();
			if (_frozen && thawPhysics)
			{
				Thaw();
			}
			_frozen = false;
		}

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

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

		private void Enforce()
		{
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			foreach (Saved<Collider> collider in _colliders)
			{
				if (Object.op_Implicit((Object)(object)collider.Part) && collider.Part.enabled)
				{
					collider.Part.enabled = false;
				}
			}
			foreach (Saved<Renderer> renderer in _renderers)
			{
				if (Object.op_Implicit((Object)(object)renderer.Part) && !renderer.Part.forceRenderingOff)
				{
					renderer.Part.forceRenderingOff = true;
				}
			}
			foreach (Saved<Light> light in _lights)
			{
				if (Object.op_Implicit((Object)(object)light.Part) && ((Behaviour)light.Part).enabled)
				{
					((Behaviour)light.Part).enabled = false;
				}
			}
			foreach (Saved<PhysGrabObjectComponentInsideBoxChecker> scanner in _scanners)
			{
				if (Object.op_Implicit((Object)(object)scanner.Part) && ((Behaviour)scanner.Part).enabled)
				{
					((Behaviour)scanner.Part).enabled = false;
				}
			}
			if (_frozen)
			{
				Rigidbody val = (Object.op_Implicit((Object)(object)Body) ? Body.rb : null);
				if (Object.op_Implicit((Object)(object)val) && !val.isKinematic)
				{
					val.velocity = Vector3.zero;
					val.angularVelocity = Vector3.zero;
					val.isKinematic = true;
				}
			}
		}

		private void Freeze()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody val = (Object.op_Implicit((Object)(object)Body) ? Body.rb : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				_wasKinematic = val.isKinematic;
				_interpolation = val.interpolation;
				if (!val.isKinematic)
				{
					val.velocity = Vector3.zero;
					val.angularVelocity = Vector3.zero;
				}
				val.isKinematic = true;
				val.interpolation = (RigidbodyInterpolation)0;
				_frozen = true;
			}
		}

		private void Thaw()
		{
			//IL_0027: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody val = (Object.op_Implicit((Object)(object)Body) ? Body.rb : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				val.interpolation = _interpolation;
				val.isKinematic = _wasKinematic;
				if (!val.isKinematic)
				{
					val.velocity = Vector3.zero;
					val.angularVelocity = Vector3.zero;
					val.WakeUp();
				}
			}
		}
	}
	internal static class VaultNet
	{
		private const byte EventCode = 186;

		private const int Signature = 1346590292;

		private const byte KindCartState = 1;

		private const byte KindSnapshotRequest = 2;

		private const float RequestInterval = 1f;

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

		private static bool _listening;

		private static float _nextRequest;

		internal static void EnsureListening()
		{
			if (_listening)
			{
				return;
			}
			try
			{
				PhotonNetwork.NetworkingClient.EventReceived += OnEvent;
				_listening = true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not subscribe to cart sync events: " + ex.Message));
			}
		}

		internal static void PublishCart(CartVault vault, int targetActor)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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)
			try
			{
				if (!((Object)(object)vault == (Object)null) && vault.ViewId != 0 && SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
				{
					object[] array = new object[4]
					{
						1346590292,
						(byte)1,
						vault.ViewId,
						vault.ExportViewIds()
					};
					object obj;
					if (targetActor <= 0)
					{
						obj = (object)new RaiseEventOptions
						{
							Receivers = (ReceiverGroup)0
						};
					}
					else
					{
						RaiseEventOptions val = new RaiseEventOptions();
						val.TargetActors = new int[1] { targetActor };
						obj = val;
					}
					RaiseEventOptions val2 = (RaiseEventOptions)obj;
					PhotonNetwork.RaiseEvent((byte)186, (object)array, val2, SendOptions.SendReliable);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not send cart state: " + ex.Message));
			}
		}

		internal static void RequestSnapshot()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_0072: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient)
				{
					float unscaledTime = Time.unscaledTime;
					if (!(unscaledTime < _nextRequest))
					{
						_nextRequest = unscaledTime + 1f;
						object[] array = new object[4]
						{
							1346590292,
							(byte)2,
							0,
							new int[0]
						};
						RaiseEventOptions val = new RaiseEventOptions
						{
							Receivers = (ReceiverGroup)2
						};
						PhotonNetwork.RaiseEvent((byte)186, (object)array, val, SendOptions.SendReliable);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not request cart states: " + ex.Message));
			}
		}

		internal static void Reset()
		{
			NextAnswerByActor.Clear();
			_nextRequest = 0f;
		}

		private static void OnEvent(EventData photonEvent)
		{
			if (photonEvent.Code != 186 || !(photonEvent.CustomData is object[] array) || array.Length < 4 || !(array[0] is int num) || num != 1346590292 || !(array[1] is byte b))
			{
				return;
			}
			try
			{
				switch (b)
				{
				case 1:
					ReceiveCartState(photonEvent.Sender, array);
					break;
				case 2:
					AnswerSnapshot(photonEvent.Sender);
					break;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)$"Bad cart sync event from actor {photonEvent.Sender}: {ex.Message}");
			}
		}

		private static void ReceiveCartState(int sender, object[] content)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				return;
			}
			Player masterClient = PhotonNetwork.MasterClient;
			if (masterClient != null && sender == masterClient.ActorNumber && content[2] is int num && num != 0)
			{
				int[] itemViewIds = (content[3] as int[]) ?? new int[0];
				CartVault cartVault = VaultRegistry.FindByView(num);
				if ((Object)(object)cartVault != (Object)null)
				{
					cartVault.ApplyMirror(itemViewIds);
				}
				else
				{
					VaultRegistry.StorePendingMirror(num, itemViewIds);
				}
			}
		}

		private static void AnswerSnapshot(int sender)
		{
			if (!PhotonNetwork.IsMasterClient || sender <= 0)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (NextAnswerByActor.TryGetValue(sender, out var value) && unscaledTime < value)
			{
				return;
			}
			NextAnswerByActor[sender] = unscaledTime + 1f;
			foreach (CartVault item in VaultRegistry.All)
			{
				if ((Object)(object)item != (Object)null)
				{
					PublishCart(item, sender);
				}
			}
		}
	}
	internal static class VaultRegistry
	{
		private static readonly List<CartVault> Vaults = new List<CartVault>();

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

		private static readonly Dictionary<int, CartVault> ByView = 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 readonly Dictionary<int, int[]> PendingMirrors = new Dictionary<int, int[]>();

		internal static IReadOnlyList<CartVault> All => Vaults;

		internal static void Register(CartVault vault, ValueScreen screen)
		{
			if (!Vaults.Contains(vault))
			{
				Vaults.Add(vault);
			}
			if (Object.op_Implicit((Object)(object)screen))
			{
				ByScreen[((Object)screen).GetInstanceID()] = vault;
			}
			if (vault.ViewId != 0)
			{
				ByView[vault.ViewId] = vault;
			}
		}

		internal static void Unregister(CartVault vault)
		{
			Vaults.Remove(vault);
			RemoveValue(ByScreen, vault);
			RemoveValue(ByView, 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 CartVault FindByView(int viewId)
		{
			if (viewId == 0 || !ByView.TryGetValue(viewId, out var value))
			{
				return null;
			}
			return value;
		}

		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 StorePendingMirror(int cartViewId, int[] itemViewIds)
		{
			PendingMirrors[cartViewId] = itemViewIds;
		}

		internal static int[] TakePendingMirror(int cartViewId)
		{
			if (!PendingMirrors.TryGetValue(cartViewId, out var value))
			{
				return null;
			}
			PendingMirrors.Remove(cartViewId);
			return value;
		}

		internal static void Reset()
		{
			Vaults.Clear();
			ByScreen.Clear();
			ByView.Clear();
			Holders.Clear();
			IntakeLocks.Clear();
			PendingMirrors.Clear();
			VaultNet.Reset();
		}

		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);
			}
		}
	}
}