Decompiled source of Pockets v1.0.1

Pockets.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Pockets.Api;
using Pockets.Domain;
using Pockets.Net;
using Pockets.Ui;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("Osmar Briones")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+b89fdcfa9af60dd2cfac68d7713632ae2f78249e")]
[assembly: AssemblyProduct("Pockets")]
[assembly: AssemblyTitle("Pockets")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Pockets
{
	internal class ConfigurationController
	{
		private static ConfigFile? ConfigFile { get; set; }

		private static ConfigEntry<bool>? Enabled { get; set; }

		private static ConfigEntry<PocketSize>? MaxValuableSizeEntry { get; set; }

		private static ConfigEntry<bool>? DropOnDeathEntry { get; set; }

		private static ConfigEntry<bool>? ShowSlotValueEntry { get; set; }

		private static ConfigEntry<bool>? EnableIconBake { get; set; }

		internal static bool IsEnabled => Enabled?.Value ?? true;

		internal static PocketSize LocalMaxValuableSize => MaxValuableSizeEntry?.Value ?? PocketSize.Tiny;

		internal static bool LocalDropOnDeath => DropOnDeathEntry?.Value ?? true;

		internal static PocketSize MaxValuableSize
		{
			get
			{
				if (!HostSettings.TryGetMaxSize(out var size))
				{
					return LocalMaxValuableSize;
				}
				return size;
			}
		}

		internal static bool DropOnDeath
		{
			get
			{
				if (!HostSettings.TryGetDropOnDeath(out var drop))
				{
					return LocalDropOnDeath;
				}
				return drop;
			}
		}

		internal static bool ShowSlotValue
		{
			get
			{
				ConfigEntry<bool>? showSlotValueEntry = ShowSlotValueEntry;
				if (showSlotValueEntry != null && !showSlotValueEntry.Value)
				{
					return PocketsApi.SlotValueRequired;
				}
				return true;
			}
		}

		internal static bool IconBakeEnabled => EnableIconBake?.Value ?? false;

		internal static void Initialize(ConfigFile config)
		{
			ConfigFile = config;
			Enabled = ConfigFile.Bind<bool>("General", "Enabled", true, "Enable or disable this mod. Turning it off drops whatever is in your pockets.");
			Enabled.SettingChanged += delegate
			{
				OnEnabledChanged();
			};
			MaxValuableSizeEntry = ConfigFile.Bind<PocketSize>("General", "MaxValuableSize", PocketSize.Tiny, "Largest valuable that can be stored in a pocket. Every size up to this one is accepted (Tiny, Small, Medium, Big, Wide, Tall, VeryTall). The host's value is used.");
			DropOnDeathEntry = ConfigFile.Bind<bool>("General", "DropOnDeath", true, "Drop the valuables stored in your pockets where you die. The host's value is used.");
			ShowSlotValueEntry = ConfigFile.Bind<bool>("Display", "ShowSlotValue", true, "Show the stored valuable's current value on its inventory slot. Other mods that depend on the value turn it on regardless of this setting.");
			EnableIconBake = ConfigFile.Bind<bool>("Debug", "EnableIconBake", false, "Developer only. Press F10 inside a level to render a picture of every valuable to BepInEx/PocketIcons.");
			ConfigFile.Save();
		}

		private static void OnEnabledChanged()
		{
			if (!IsEnabled)
			{
				PocketReleaser.ReleaseLocalPockets();
			}
		}

		internal static void Reload()
		{
			ConfigFile? configFile = ConfigFile;
			if (configFile != null)
			{
				configFile.Reload();
			}
			ConfigFile? configFile2 = ConfigFile;
			if (configFile2 != null)
			{
				configFile2.Save();
			}
		}
	}
	[BepInPlugin("com.osmar.Pockets", "Pockets", "1.0.1")]
	public class PocketsPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.osmar.Pockets";

		public const string PluginName = "Pockets";

		public const string PluginVersion = "1.0.1";

		internal Harmony? Harmony { get; set; }

		internal static ManualLogSource Logger { get; private set; }

		private void Awake()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			ConfigurationController.Initialize(((BaseUnityPlugin)this).Config);
			((Component)this).gameObject.AddComponent<PocketsRoomEvents>();
			if (ConfigurationController.IconBakeEnabled)
			{
				((Component)this).gameObject.AddComponent<IconBaker>();
				Logger.LogWarning((object)"Icon baking is enabled (Debug.EnableIconBake): press F10 inside a level. Developer use only.");
			}
			Harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
			Harmony.PatchAll();
			Logger.LogInfo((object)"Pockets 1.0.1 loaded!");
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace Pockets.Ui
{
	internal sealed class IconBaker : MonoBehaviour
	{
		private static readonly string[] Folders = new string[7] { "valuables/01 tiny", "valuables/02 small", "valuables/03 medium", "valuables/04 big", "valuables/05 wide", "valuables/06 tall", "valuables/07 very tall" };

		private const int BakeSize = 256;

		private bool running;

		private void Update()
		{
			Keyboard current = Keyboard.current;
			if (current != null && ((ButtonControl)current.f10Key).wasPressedThisFrame && !running)
			{
				((MonoBehaviour)this).StartCoroutine(Bake());
			}
		}

		private IEnumerator Bake()
		{
			running = true;
			string outputFolder = Path.Combine(Paths.BepInExRootPath, "PocketIcons");
			Directory.CreateDirectory(outputFolder);
			PocketsPlugin.Logger.LogInfo((object)("[Icon bake] started, writing to " + outputFolder));
			int saved = 0;
			int failed = 0;
			string[] folders = Folders;
			foreach (string text in folders)
			{
				GameObject[] array = Resources.LoadAll<GameObject>(text);
				PocketsPlugin.Logger.LogInfo((object)$"[Icon bake] {text}: {array.Length} prefabs");
				GameObject[] array2 = array;
				foreach (GameObject val in array2)
				{
					string text2 = ValuableIconRenderer.KeyOf(val);
					Texture2D val2 = null;
					try
					{
						val2 = ValuableIconRenderer.RenderTexture2D(val, 256);
						if ((Object)(object)val2 != (Object)null)
						{
							File.WriteAllBytes(Path.Combine(outputFolder, text2 + ".png"), ImageConversion.EncodeToPNG(val2));
							saved++;
						}
						else
						{
							failed++;
							PocketsPlugin.Logger.LogWarning((object)("[Icon bake] nothing to draw for " + text2));
						}
					}
					catch (Exception ex)
					{
						failed++;
						PocketsPlugin.Logger.LogWarning((object)("[Icon bake] " + text2 + " failed: " + ex.Message));
					}
					finally
					{
						if ((Object)(object)val2 != (Object)null)
						{
							Object.Destroy((Object)(object)val2);
						}
					}
					yield return null;
				}
			}
			PocketsPlugin.Logger.LogInfo((object)$"[Icon bake] done: {saved} saved, {failed} failed");
			running = false;
		}
	}
	internal sealed class PocketSlotView : MonoBehaviour
	{
		private const float LabelRefreshSeconds = 0.25f;

		private InventorySpot spot;

		private TextMeshProUGUI? valueLabel;

		private float nextLabelRefresh;

		internal static PocketSlotView GetOrAdd(InventorySpot spot)
		{
			PocketSlotView pocketSlotView = ((Component)spot).GetComponent<PocketSlotView>();
			if ((Object)(object)pocketSlotView == (Object)null)
			{
				pocketSlotView = ((Component)spot).gameObject.AddComponent<PocketSlotView>();
			}
			return pocketSlotView;
		}

		private void Awake()
		{
			spot = ((Component)this).GetComponent<InventorySpot>();
		}

		private void Update()
		{
			if (!(Time.unscaledTime < nextLabelRefresh))
			{
				nextLabelRefresh = Time.unscaledTime + 0.25f;
				ValuableObject val = CurrentValuable();
				if ((Object)(object)val != (Object)null)
				{
					ShowLabel(val);
				}
			}
		}

		internal void Refresh()
		{
			ValuableObject val = CurrentValuable();
			if ((Object)(object)val == (Object)null)
			{
				HideLabel();
				return;
			}
			spot.SetEmoji(ValuableIconRenderer.Get(((Component)val).gameObject));
			ShowLabel(val);
		}

		private ValuableObject? CurrentValuable()
		{
			if ((Object)(object)spot == (Object)null || !SemiFunc.RunIsLevel())
			{
				return null;
			}
			int num = PlayerKeys.Local();
			if (num == int.MinValue)
			{
				return null;
			}
			PlayerPockets playerPockets = PocketsApi.Find(num);
			int inventorySpotIndex = spot.inventorySpotIndex;
			if (playerPockets == null || inventorySpotIndex < 0 || inventorySpotIndex >= playerPockets.Valuables.Length)
			{
				return null;
			}
			return playerPockets.Valuables[inventorySpotIndex];
		}

		private void ShowLabel(ValuableObject valuable)
		{
			if (!ConfigurationController.ShowSlotValue)
			{
				HideLabel();
				return;
			}
			TextMeshProUGUI val = EnsureLabel();
			if (!((Object)(object)val == (Object)null))
			{
				((TMP_Text)val).text = FormatValue(valuable.dollarValueCurrent);
				((Behaviour)val).enabled = true;
			}
		}

		private void HideLabel()
		{
			if ((Object)(object)valueLabel != (Object)null)
			{
				((Behaviour)valueLabel).enabled = false;
			}
		}

		private TextMeshProUGUI? EnsureLabel()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)valueLabel != (Object)null)
			{
				return valueLabel;
			}
			TextMeshProUGUI noItem = spot.noItem;
			if ((Object)(object)noItem == (Object)null)
			{
				return null;
			}
			valueLabel = Object.Instantiate<TextMeshProUGUI>(noItem, ((TMP_Text)noItem).transform.parent);
			((Object)valueLabel).name = "PocketValue";
			((TMP_Text)valueLabel).alignment = (TextAlignmentOptions)514;
			((TMP_Text)valueLabel).enableAutoSizing = false;
			((TMP_Text)valueLabel).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)valueLabel).overflowMode = (TextOverflowModes)0;
			((TMP_Text)valueLabel).fontSize = ((TMP_Text)noItem).fontSize * 0.55f;
			((Graphic)valueLabel).color = Color.white;
			((Graphic)valueLabel).raycastTarget = false;
			((TMP_Text)valueLabel).outlineWidth = 0.3f;
			((TMP_Text)valueLabel).outlineColor = new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue);
			if ((Object)(object)spot.inventoryIcon != (Object)null)
			{
				RectTransform rectTransform = ((Graphic)spot.inventoryIcon).rectTransform;
				float num = ((TMP_Text)valueLabel).fontSize * 0.7f;
				RectTransform rectTransform2 = ((TMP_Text)valueLabel).rectTransform;
				Vector2 anchoredPosition = rectTransform.anchoredPosition;
				Rect rect = rectTransform.rect;
				rectTransform2.anchoredPosition = anchoredPosition + new Vector2(0f, ((Rect)(ref rect)).yMin + num);
			}
			return valueLabel;
		}

		private static string FormatValue(float value)
		{
			if (!(value >= 1000f))
			{
				return "$" + value.ToString("0", CultureInfo.InvariantCulture);
			}
			return "$" + (value / 1000f).ToString("0.#", CultureInfo.InvariantCulture) + "K";
		}
	}
	internal static class ValuableIconRenderer
	{
		private readonly struct Part
		{
			internal Mesh Mesh { get; }

			internal Material[] Materials { get; }

			internal Matrix4x4 Matrix { get; }

			internal Part(Mesh mesh, Material[] materials, Matrix4x4 matrix)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				Mesh = mesh;
				Materials = materials;
				Matrix = matrix;
			}
		}

		internal const int Size = 128;

		private const float FieldOfView = 30f;

		private const string EmbeddedPrefix = "Pockets.Icons.";

		private static readonly Vector3 FarOrigin = new Vector3(0f, 5000f, 0f);

		private static readonly Dictionary<string, Sprite> Cache = new Dictionary<string, Sprite>();

		private static Sprite? fallback;

		internal static Sprite Fallback
		{
			get
			{
				if ((Object)(object)fallback == (Object)null)
				{
					fallback = CreateFallback();
				}
				return fallback;
			}
		}

		internal static string KeyOf(GameObject valuable)
		{
			return ((Object)valuable).name.Replace("(Clone)", string.Empty).Trim();
		}

		internal static void Ensure(GameObject valuable)
		{
			//IL_006c: 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)
			string text = KeyOf(valuable);
			if (Cache.TryGetValue(text, out Sprite value) && (Object)(object)value != (Object)null)
			{
				return;
			}
			Sprite val = LoadEmbedded(text);
			string text2 = "packaged";
			if ((Object)(object)val == (Object)null)
			{
				text2 = "rendered";
				try
				{
					Texture2D val2 = RenderTexture2D(valuable);
					val = (((Object)(object)val2 != (Object)null) ? Sprite.Create(val2, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f)) : null);
				}
				catch (Exception ex)
				{
					PocketsPlugin.Logger.LogWarning((object)("Could not render an icon for " + text + ": " + ex.Message));
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				text2 = "generic";
			}
			PocketsPlugin.Logger.LogInfo((object)("Icon for " + text + ": " + text2));
			Cache[text] = (Sprite)(((Object)(object)val != (Object)null) ? ((object)val) : ((object)Fallback));
		}

		internal static Sprite Get(GameObject valuable)
		{
			if (!Cache.TryGetValue(KeyOf(valuable), out Sprite value) || !((Object)(object)value != (Object)null))
			{
				return Fallback;
			}
			return value;
		}

		private static Sprite? LoadEmbedded(string key)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Pockets.Icons." + key + ".png");
				if (stream == null)
				{
					return null;
				}
				byte[] array = new byte[stream.Length];
				int num;
				for (int i = 0; i < array.Length; i += num)
				{
					num = stream.Read(array, i, array.Length - i);
					if (num <= 0)
					{
						break;
					}
				}
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!TryDecodePng(val, array))
				{
					Object.Destroy((Object)(object)val);
					return null;
				}
				return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
			}
			catch (Exception ex)
			{
				PocketsPlugin.Logger.LogWarning((object)("Could not load the packaged icon for " + key + ": " + ex.Message));
				return null;
			}
		}

		private static bool TryDecodePng(Texture2D texture, byte[] bytes)
		{
			MethodInfo method = typeof(ImageConversion).GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
			{
				typeof(Texture2D),
				typeof(byte[])
			}, null);
			if (method != null)
			{
				object obj = method.Invoke(null, new object[2] { texture, bytes });
				if (obj is bool)
				{
					return (bool)obj;
				}
				return false;
			}
			return false;
		}

		internal static Texture2D? RenderTexture2D(GameObject source, int size = 128)
		{
			//IL_0008: 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_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Expected O, but got Unknown
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Expected O, but got Unknown
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Expected O, but got Unknown
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			List<Part> list = new List<Part>();
			Bounds bounds = default(Bounds);
			bool flag = false;
			Matrix4x4 worldToLocalMatrix = source.transform.worldToLocalMatrix;
			MeshRenderer[] componentsInChildren = source.GetComponentsInChildren<MeshRenderer>();
			MeshFilter val2 = default(MeshFilter);
			foreach (MeshRenderer val in componentsInChildren)
			{
				if (!((Renderer)val).enabled || !((Component)val).gameObject.activeSelf || !((Component)val).TryGetComponent<MeshFilter>(ref val2) || (Object)(object)val2.sharedMesh == (Object)null)
				{
					continue;
				}
				Material[] sharedMaterials = ((Renderer)val).sharedMaterials;
				if (sharedMaterials.Length != 0)
				{
					Matrix4x4 matrix = worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix;
					list.Add(new Part(val2.sharedMesh, sharedMaterials, matrix));
					Bounds val3 = TransformBounds(val2.sharedMesh.bounds, matrix);
					if (flag)
					{
						((Bounds)(ref bounds)).Encapsulate(val3);
						continue;
					}
					bounds = val3;
					flag = true;
				}
			}
			if (!flag)
			{
				return null;
			}
			Vector3 val4 = ((Bounds)(ref bounds)).extents;
			float num = Mathf.Max(((Vector3)(ref val4)).magnitude, 0.001f);
			val4 = new Vector3(0.6f, 0.45f, -1f);
			Vector3 normalized = ((Vector3)(ref val4)).normalized;
			float num2 = FitDistance(bounds, normalized, num);
			Vector3 position = FarOrigin + normalized * num2;
			AmbientMode ambientMode = RenderSettings.ambientMode;
			Color ambientLight = RenderSettings.ambientLight;
			bool fog = RenderSettings.fog;
			RenderTexture val5 = new RenderTexture(size, size, 24, (RenderTextureFormat)0);
			GameObject val6 = new GameObject("PocketsIconCamera")
			{
				hideFlags = (HideFlags)61
			};
			GameObject val7 = new GameObject("PocketsIconLights")
			{
				hideFlags = (HideFlags)61
			};
			RenderTexture active = RenderTexture.active;
			try
			{
				RenderSettings.ambientMode = (AmbientMode)3;
				RenderSettings.ambientLight = new Color(0.55f, 0.55f, 0.55f);
				RenderSettings.fog = false;
				Camera val8 = val6.AddComponent<Camera>();
				((Behaviour)val8).enabled = false;
				val8.clearFlags = (CameraClearFlags)2;
				val8.backgroundColor = new Color(0f, 0f, 0f, 0f);
				val8.cullingMask = 1;
				val8.nearClipPlane = 0.001f;
				val8.farClipPlane = num2 + num * 4f;
				val8.fieldOfView = 30f;
				val8.allowHDR = false;
				val8.allowMSAA = false;
				val8.targetTexture = val5;
				((Component)val8).transform.position = position;
				((Component)val8).transform.LookAt(FarOrigin);
				AddLight(val7, "Key", 1f, Quaternion.LookRotation(new Vector3(-0.5f, -0.7f, 0.6f)));
				AddLight(val7, "Fill", 0.45f, Quaternion.LookRotation(new Vector3(0.7f, -0.2f, 0.5f)));
				foreach (Part item in list)
				{
					Matrix4x4 val9 = Matrix4x4.Translate(FarOrigin - ((Bounds)(ref bounds)).center) * item.Matrix;
					for (int j = 0; j < item.Mesh.subMeshCount; j++)
					{
						Graphics.DrawMesh(item.Mesh, val9, item.Materials[Mathf.Min(j, item.Materials.Length - 1)], 0, val8, j);
					}
				}
				val8.Render();
				RenderTexture.active = val5;
				Texture2D val10 = new Texture2D(size, size, (TextureFormat)4, false);
				val10.ReadPixels(new Rect(0f, 0f, (float)size, (float)size), 0, 0);
				val10.Apply();
				if (!HasVisiblePixels(val10))
				{
					Object.Destroy((Object)(object)val10);
					return null;
				}
				return val10;
			}
			finally
			{
				RenderTexture.active = active;
				RenderSettings.ambientMode = ambientMode;
				RenderSettings.ambientLight = ambientLight;
				RenderSettings.fog = fog;
				Light[] componentsInChildren2 = val7.GetComponentsInChildren<Light>();
				for (int i = 0; i < componentsInChildren2.Length; i++)
				{
					((Behaviour)componentsInChildren2[i]).enabled = false;
				}
				val7.SetActive(false);
				Object.Destroy((Object)(object)val7);
				Object.Destroy((Object)(object)val6);
				val5.Release();
				Object.Destroy((Object)(object)val5);
			}
		}

		private static float FitDistance(Bounds bounds, Vector3 direction, float radius)
		{
			//IL_0011: 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_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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_002d: 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)
			//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_005c: 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_007d: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Tan((float)Math.PI / 12f) * 0.94f;
			Vector3 val = -direction;
			Vector3 val2 = Vector3.Cross(Vector3.up, val);
			Vector3 normalized = ((Vector3)(ref val2)).normalized;
			Vector3 val3 = Vector3.Cross(val, normalized);
			float num2 = radius * 0.5f;
			for (int i = 0; i < 8; i++)
			{
				Vector3 val4 = new Vector3(((i & 1) == 0) ? (0f - ((Bounds)(ref bounds)).extents.x) : ((Bounds)(ref bounds)).extents.x, ((i & 2) == 0) ? (0f - ((Bounds)(ref bounds)).extents.y) : ((Bounds)(ref bounds)).extents.y, ((i & 4) == 0) ? (0f - ((Bounds)(ref bounds)).extents.z) : ((Bounds)(ref bounds)).extents.z);
				float num3 = Vector3.Dot(val4, normalized);
				float num4 = Vector3.Dot(val4, val3);
				float num5 = Vector3.Dot(val4, val);
				num2 = Mathf.Max(new float[3]
				{
					num2,
					Mathf.Abs(num3) / num - num5,
					Mathf.Abs(num4) / num - num5
				});
			}
			return num2 * 1.04f;
		}

		private static void AddLight(GameObject parent, string name, float intensity, Quaternion rotation)
		{
			//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_000e: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name)
			{
				hideFlags = (HideFlags)61
			};
			val.transform.SetParent(parent.transform, false);
			val.transform.rotation = rotation;
			Light obj = val.AddComponent<Light>();
			obj.type = (LightType)1;
			obj.intensity = intensity;
			obj.shadows = (LightShadows)0;
			obj.cullingMask = 1;
		}

		private static Bounds TransformBounds(Bounds local, Matrix4x4 matrix)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_005c: 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)
			//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_006f: 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_0086: 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_009d: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Matrix4x4)(ref matrix)).MultiplyPoint3x4(((Bounds)(ref local)).center);
			Vector3 extents = ((Bounds)(ref local)).extents;
			Vector3 val2 = ((Matrix4x4)(ref matrix)).MultiplyVector(new Vector3(extents.x, 0f, 0f));
			Vector3 val3 = ((Matrix4x4)(ref matrix)).MultiplyVector(new Vector3(0f, extents.y, 0f));
			Vector3 val4 = ((Matrix4x4)(ref matrix)).MultiplyVector(new Vector3(0f, 0f, extents.z));
			Vector3 val5 = default(Vector3);
			((Vector3)(ref val5))..ctor(Mathf.Abs(val2.x) + Mathf.Abs(val3.x) + Mathf.Abs(val4.x), Mathf.Abs(val2.y) + Mathf.Abs(val3.y) + Mathf.Abs(val4.y), Mathf.Abs(val2.z) + Mathf.Abs(val3.z) + Mathf.Abs(val4.z));
			return new Bounds(val, val5 * 2f);
		}

		private static bool HasVisiblePixels(Texture2D texture)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Color32[] pixels = texture.GetPixels32();
			int num = 0;
			Color32[] array = pixels;
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i].a > 12)
				{
					num++;
				}
			}
			return num > pixels.Length / 50;
		}

		private static Sprite CreateFallback()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0f, 0f, 0f, 0f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(1f, 0.82f, 0.25f, 1f);
			Color val4 = default(Color);
			((Color)(ref val4))..ctor(0.65f, 0.45f, 0.1f, 1f);
			float num = 31.5f;
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num2 = Mathf.Abs((float)j - num) + Mathf.Abs((float)i - num);
					val.SetPixel(j, i, (num2 < num * 0.8f) ? val3 : ((num2 < num * 0.95f) ? val4 : val2));
				}
			}
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
		}
	}
}
namespace Pockets.Patches
{
	[HarmonyPatch(typeof(EnemyDirector), "Start")]
	internal static class EnemyDirector_Start_Patch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			if (SemiFunc.RunIsLevel())
			{
				ConfigurationController.Reload();
				PocketsApi.ClearAll();
				HostSettings.Publish();
			}
		}
	}
	[HarmonyPatch(typeof(InventorySpot), "HandleInput")]
	internal static class InventorySpot_HandleInput_Patch
	{
		private const float RequestCooldownSeconds = 0.2f;

		private static float lastRequestTime = -1f;

		[HarmonyPrefix]
		private static bool Prefix(InventorySpot __instance)
		{
			if (!SemiFunc.RunIsLevel())
			{
				return true;
			}
			int num = PlayerKeys.Local();
			if (num == int.MinValue)
			{
				return true;
			}
			int inventorySpotIndex = __instance.inventorySpotIndex;
			PlayerPockets playerPockets = PocketsApi.Find(num);
			if (playerPockets != null && playerPockets.State.IsOccupied(inventorySpotIndex))
			{
				if (CanSendRequest())
				{
					ValuableObject val = playerPockets.Valuables[inventorySpotIndex];
					PocketedValuable pocketedValuable = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<PocketedValuable>() : null);
					if ((Object)(object)pocketedValuable != (Object)null)
					{
						pocketedValuable.RequestRelease();
					}
					else
					{
						PocketsPlugin.Logger.LogWarning((object)$"Slot {inventorySpotIndex + 1} held a valuable that no longer exists; freeing the slot.");
						PocketsApi.Forget(num, inventorySpotIndex);
					}
				}
				return false;
			}
			if (!ConfigurationController.IsEnabled || __instance.IsOccupied())
			{
				return true;
			}
			PocketedValuable pocketedValuable2 = HeldValuable();
			if ((Object)(object)pocketedValuable2 == (Object)null || !PocketSync.IsSizeAccepted(pocketedValuable2.Valuable))
			{
				return true;
			}
			if (CanSendRequest())
			{
				PocketsPlugin.Logger.LogInfo((object)$"Slot {inventorySpotIndex + 1} pressed holding {((Object)pocketedValuable2).name}: asking to store it");
				pocketedValuable2.RequestStore(inventorySpotIndex);
			}
			return false;
		}

		private static bool CanSendRequest()
		{
			if (PlayerController.instance.InputDisableTimer > 0f || Time.time - lastRequestTime < 0.2f)
			{
				return false;
			}
			lastRequestTime = Time.time;
			return true;
		}

		private static PocketedValuable? HeldValuable()
		{
			PhysGrabber instance = PhysGrabber.instance;
			if ((Object)(object)instance == (Object)null || !instance.grabbed || (Object)(object)instance.grabbedPhysGrabObject == (Object)null)
			{
				return null;
			}
			return ((Component)instance.grabbedPhysGrabObject).GetComponent<PocketedValuable>();
		}
	}
	[HarmonyPatch(typeof(InventorySpot), "IsOccupied")]
	internal static class InventorySpot_Occupied_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(InventorySpot __instance, ref bool __result)
		{
			if (__result || !SemiFunc.RunIsLevel())
			{
				return;
			}
			int num = PlayerKeys.Local();
			if (num != int.MinValue)
			{
				PlayerPockets playerPockets = PocketsApi.Find(num);
				if (playerPockets != null && playerPockets.State.IsOccupied(__instance.inventorySpotIndex))
				{
					__result = true;
				}
			}
		}
	}
	[HarmonyPatch(typeof(InventorySpot), "UpdateUI")]
	internal static class InventorySpot_UI_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(InventorySpot __instance)
		{
			PocketSlotView.GetOrAdd(__instance).Refresh();
		}
	}
	[HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")]
	internal static class PlayerAvatar_PlayerDeathRPC_Patch
	{
		[HarmonyPrefix]
		private static void Prefix(PlayerAvatar __instance, out bool __state)
		{
			__state = __instance.deadSet;
		}

		[HarmonyPostfix]
		private static void Postfix(PlayerAvatar __instance, bool __state)
		{
			if (__state || !__instance.deadSet || !SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			int playerKey = PlayerKeys.Of(__instance);
			PlayerPockets playerPockets = PocketsApi.Find(playerKey);
			if (playerPockets != null && playerPockets.State.OccupiedCount != 0 && !PocketsApi.RaisePlayerDying(playerKey) && ConfigurationController.DropOnDeath)
			{
				for (int i = 0; i < playerPockets.Valuables.Length; i++)
				{
					PocketsApi.TryRemove(playerKey, i);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ValuableObject), "AddToDollarHaulList")]
	internal static class ValuableObject_AddToDollarHaulList_Patch
	{
		[HarmonyPrefix]
		private static bool Prefix(ValuableObject __instance)
		{
			PocketedValuable component = ((Component)__instance).GetComponent<PocketedValuable>();
			if (!((Object)(object)component == (Object)null))
			{
				return !component.IsPocketed;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ValuableObject), "Start")]
	internal static class ValuableObject_Start_Patch
	{
		[HarmonyPostfix]
		private static void Postfix(ValuableObject __instance)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<PocketedValuable>() != (Object)null))
			{
				((Component)__instance).gameObject.AddComponent<PocketedValuable>();
				PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
				if ((Object)(object)component != (Object)null)
				{
					component.RefreshRpcMonoBehaviourCache();
				}
			}
		}
	}
}
namespace Pockets.Net
{
	internal static class HostSettings
	{
		private const string MaxSizeKey = "pockets.maxSize";

		private const string DropOnDeathKey = "pockets.dropOnDeath";

		private static bool UseHostValues
		{
			get
			{
				if (PhotonNetwork.InRoom)
				{
					return !PhotonNetwork.IsMasterClient;
				}
				return false;
			}
		}

		internal static void Publish()
		{
			//IL_0014: 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_002e: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_004a: Expected O, but got Unknown
			if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
			{
				Room currentRoom = PhotonNetwork.CurrentRoom;
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)"pockets.maxSize", (object)(int)ConfigurationController.LocalMaxValuableSize);
				((Dictionary<object, object>)val).Add((object)"pockets.dropOnDeath", (object)ConfigurationController.LocalDropOnDeath);
				currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
			}
		}

		internal static bool TryGetMaxSize(out PocketSize size)
		{
			size = PocketSize.Tiny;
			if (!UseHostValues || !((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"pockets.maxSize", out object value) || !(value is int gameVolume))
			{
				return false;
			}
			return SizePolicy.TryFromGameVolume(gameVolume, out size);
		}

		internal static bool TryGetDropOnDeath(out bool drop)
		{
			drop = true;
			if (!UseHostValues || !((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"pockets.dropOnDeath", out object value) || !(value is bool flag))
			{
				return false;
			}
			drop = flag;
			return true;
		}
	}
	internal static class PlayerKeys
	{
		internal const int SingleplayerKey = -1;

		internal const int NoPlayer = int.MinValue;

		internal static int Of(PlayerAvatar avatar)
		{
			if (!SemiFunc.IsMultiplayer())
			{
				return -1;
			}
			return avatar.photonView.ViewID;
		}

		internal static int Local()
		{
			PlayerAvatar instance = PlayerAvatar.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				return Of(instance);
			}
			return int.MinValue;
		}

		internal static PlayerAvatar? Resolve(int playerKey)
		{
			if (!SemiFunc.IsMultiplayer())
			{
				return PlayerAvatar.instance;
			}
			return SemiFunc.PlayerAvatarGetFromPhotonID(playerKey);
		}
	}
	internal sealed class PocketedValuable : MonoBehaviourPun
	{
		private const float HiddenScaleFactor = 0.01f;

		private const float ReleaseDistance = 1.5f;

		private const float MaxReleaseDistanceFromPlayer = 10f;

		private const float AutoGrabSeconds = 1.5f;

		private PhysGrabObject physGrabObject;

		private ValuableObject valuable;

		private Rigidbody? body;

		private Collider[] colliders = (Collider[])(object)new Collider[0];

		private bool[] colliderStates = new bool[0];

		private Vector3 originalScale = Vector3.one;

		private bool bodyWasKinematic;

		private float releaseOffset;

		internal ValuableObject Valuable => valuable;

		internal PhysGrabObject PhysGrabObject => physGrabObject;

		internal bool IsPocketed { get; private set; }

		internal int PlayerKey { get; private set; } = int.MinValue;

		internal int Slot { get; private set; } = -1;

		internal int Key
		{
			get
			{
				if (!SemiFunc.IsMultiplayer())
				{
					return ((Object)((Component)this).gameObject).GetInstanceID();
				}
				return ((MonoBehaviourPun)this).photonView.ViewID;
			}
		}

		private void Awake()
		{
			physGrabObject = ((Component)this).GetComponent<PhysGrabObject>();
			valuable = ((Component)this).GetComponent<ValuableObject>();
			body = ((Component)this).GetComponent<Rigidbody>();
		}

		private void Update()
		{
			if (IsPocketed)
			{
				physGrabObject.OverrideDeactivate(0.1f);
			}
		}

		private void OnDestroy()
		{
			if (!IsPocketed)
			{
				return;
			}
			int playerKey = PlayerKey;
			int slot = Slot;
			int key = Key;
			PocketsApi.Forget(playerKey, slot);
			try
			{
				PocketsApi.RaiseRemoved(new PocketEvent(playerKey, slot, key, null));
				RefreshLocalSlot(playerKey, slot);
			}
			catch (Exception ex)
			{
				PocketsPlugin.Logger.LogWarning((object)$"Could not refresh slot {slot} after {((Object)this).name} was destroyed: {ex.Message}");
			}
		}

		internal void RequestStore(int slot)
		{
			PlayerAvatar instance = PlayerAvatar.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				int num = PlayerKeys.Of(instance);
				if (SemiFunc.IsMultiplayer())
				{
					((MonoBehaviourPun)this).photonView.RPC("RequestStoreRpc", (RpcTarget)2, new object[2] { slot, num });
				}
				else
				{
					ProcessStoreRequest(slot, num);
				}
			}
		}

		[PunRPC]
		private void RequestStoreRpc(int slot, int playerKey, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClient())
			{
				PlayerAvatar val = PlayerKeys.Resolve(playerKey);
				if (!((Object)(object)val == (Object)null) && SemiFunc.MasterAndOwnerOnlyRPC(info, val.photonView))
				{
					ProcessStoreRequest(slot, playerKey);
				}
			}
		}

		private void ProcessStoreRequest(int slot, int playerKey)
		{
			if (!PocketSync.CanStore(this, slot, playerKey, out string reason))
			{
				PocketsPlugin.Logger.LogInfo((object)("Store refused for " + ((Object)this).name + ": " + reason));
			}
			else if (SemiFunc.IsMultiplayer())
			{
				((MonoBehaviourPun)this).photonView.RPC("StoredRpc", (RpcTarget)0, new object[2] { playerKey, slot });
			}
			else
			{
				ApplyStored(playerKey, slot);
			}
		}

		[PunRPC]
		private void StoredRpc(int playerKey, int slot, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.MasterOnlyRPC(info))
			{
				ApplyStored(playerKey, slot);
			}
		}

		private void ApplyStored(int playerKey, int slot)
		{
			PlayerPockets orCreate = PocketsApi.GetOrCreate(playerKey);
			if (IsPocketed || !orCreate.State.TryStore(slot, Key))
			{
				PocketsPlugin.Logger.LogWarning((object)$"Could not register {((Object)this).name} in slot {slot} of player {playerKey}; ignoring the store.");
				return;
			}
			orCreate.Valuables[slot] = valuable;
			IsPocketed = true;
			PlayerKey = playerKey;
			Slot = slot;
			if (playerKey == PlayerKeys.Local())
			{
				ValuableIconRenderer.Ensure(((Component)this).gameObject);
			}
			Hide();
			PocketsPlugin.Logger.LogInfo((object)$"Stored {((Object)this).name} (value {valuable.dollarValueCurrent:F0}) in slot {slot} of player {playerKey}");
			PocketsApi.RaiseStored(new PocketEvent(playerKey, slot, Key, valuable));
			RefreshLocalSlot(playerKey, slot);
		}

		internal void SendStateTo(Player target, int playerKey, int slot)
		{
			if (SemiFunc.IsMultiplayer() && IsPocketed)
			{
				((MonoBehaviourPun)this).photonView.RPC("StoredRpc", target, new object[2] { playerKey, slot });
			}
		}

		internal void RequestRelease(bool autoGrab = true, int spread = 0)
		{
			//IL_0094: 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_0068: 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)
			PlayerAvatar instance = PlayerAvatar.instance;
			if (!((Object)(object)instance == (Object)null) && IsPocketed && PlayerKey == PlayerKeys.Of(instance))
			{
				ComputeReleasePose(spread, out var position, out var rotation);
				if (SemiFunc.IsMultiplayer())
				{
					((MonoBehaviourPun)this).photonView.RPC("RequestReleaseRpc", (RpcTarget)2, new object[5] { Slot, PlayerKey, position, rotation, autoGrab });
				}
				else
				{
					ProcessReleaseRequest(Slot, PlayerKey, position, rotation, autoGrab);
				}
			}
		}

		[PunRPC]
		private void RequestReleaseRpc(int slot, int playerKey, Vector3 position, Quaternion rotation, bool autoGrab, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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)
			if (SemiFunc.IsMasterClient())
			{
				PlayerAvatar val = PlayerKeys.Resolve(playerKey);
				if (!((Object)(object)val == (Object)null) && SemiFunc.MasterAndOwnerOnlyRPC(info, val.photonView))
				{
					ProcessReleaseRequest(slot, playerKey, position, rotation, autoGrab);
				}
			}
		}

		private void ProcessReleaseRequest(int slot, int playerKey, Vector3 position, Quaternion rotation, bool autoGrab)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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)
			PlayerAvatar avatar = PlayerKeys.Resolve(playerKey);
			if (!PocketSync.CanRelease(this, slot, playerKey, position, avatar, 10f, out string reason))
			{
				PocketsPlugin.Logger.LogInfo((object)("Release refused for " + ((Object)this).name + ": " + reason));
			}
			else
			{
				BroadcastRelease(slot, playerKey, position, rotation, autoGrab);
			}
		}

		internal void BroadcastRelease(int slot, int playerKey, Vector3 position, Quaternion rotation, bool autoGrab)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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 (SemiFunc.IsMultiplayer())
			{
				((MonoBehaviourPun)this).photonView.RPC("ReleasedRpc", (RpcTarget)0, new object[5] { playerKey, slot, position, rotation, autoGrab });
			}
			else
			{
				ApplyReleased(playerKey, slot, position, rotation, autoGrab);
			}
		}

		[PunRPC]
		private void ReleasedRpc(int playerKey, int slot, Vector3 position, Quaternion rotation, bool autoGrab, PhotonMessageInfo info = default(PhotonMessageInfo))
		{
			//IL_0000: 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_000e: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.MasterOnlyRPC(info))
			{
				ApplyReleased(playerKey, slot, position, rotation, autoGrab);
			}
		}

		private void ApplyReleased(int playerKey, int slot, Vector3 position, Quaternion rotation, bool autoGrab)
		{
			//IL_0097: 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)
			PlayerPockets playerPockets = PocketsApi.Find(playerKey);
			if (!IsPocketed || PlayerKey != playerKey || Slot != slot || playerPockets == null || !playerPockets.State.TryRelease(slot, out var _))
			{
				PocketsPlugin.Logger.LogWarning((object)$"Could not release {((Object)this).name} from slot {slot} of player {playerKey}; ignoring the release.");
				return;
			}
			int key = Key;
			playerPockets.Valuables[slot] = null;
			IsPocketed = false;
			PlayerKey = int.MinValue;
			Slot = -1;
			Show();
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				physGrabObject.Teleport(position, rotation);
			}
			PocketsPlugin.Logger.LogInfo((object)$"Released {((Object)this).name} (value {valuable.dollarValueCurrent:F0}) from slot {slot} of player {playerKey}");
			PocketsApi.RaiseRemoved(new PocketEvent(playerKey, slot, key, valuable));
			RefreshLocalSlot(playerKey, slot);
			PlayerAvatar instance = PlayerAvatar.instance;
			if (autoGrab && playerKey == PlayerKeys.Local() && (Object)(object)instance != (Object)null && !instance.deadSet)
			{
				((MonoBehaviour)this).StartCoroutine(AutoGrab());
			}
		}

		private void ComputeReleasePose(int spread, out Vector3 position, out Quaternion rotation)
		{
			//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_0045: 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_0079: 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_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_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)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_009a: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				position = ((Component)this).transform.position;
				rotation = ((Component)this).transform.rotation;
				return;
			}
			Transform transform = ((Component)main).transform;
			rotation = Quaternion.LookRotation(transform.forward, Vector3.up);
			int num = LayerMask.op_Implicit(SemiFunc.LayerMaskGetVisionObstruct()) & ~LayerMask.GetMask(new string[2] { "Ignore Raycast", "CollisionCheck" });
			RaycastHit val = default(RaycastHit);
			position = (Physics.Raycast(transform.position, transform.forward, ref val, 1.5f, num) ? (((RaycastHit)(ref val)).point + ((RaycastHit)(ref val)).normal * releaseOffset) : (transform.position + transform.forward * 1.5f));
			position += transform.right * ((float)spread * 0.25f);
		}

		private IEnumerator AutoGrab()
		{
			float timer = 1.5f;
			while (timer > 0f && (Object)(object)physGrabObject != (Object)null && (Object)(object)PhysGrabber.instance != (Object)null)
			{
				PhysGrabber.instance.OverrideGrab(physGrabObject, 0.1f, false);
				if (!SemiFunc.InputUp((InputKey)10))
				{
					timer -= Time.deltaTime;
					yield return null;
					continue;
				}
				break;
			}
		}

		private void Hide()
		{
			//IL_0073: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				foreach (PhysGrabber item in physGrabObject.playerGrabbing.ToList())
				{
					item.OverrideGrabRelease(((MonoBehaviourPun)this).photonView.ViewID, 0.5f);
				}
				if (!valuable.committedToExtraction)
				{
					valuable.RemoveFromDollarHaulList();
				}
			}
			originalScale = ((Component)this).transform.localScale;
			colliders = ((Component)this).GetComponentsInChildren<Collider>();
			colliderStates = colliders.Select((Collider collider) => collider.enabled).ToArray();
			Bounds val = default(Bounds);
			((Bounds)(ref val))..ctor(((Component)this).transform.position, Vector3.zero);
			Collider[] array = colliders;
			foreach (Collider val2 in array)
			{
				((Bounds)(ref val)).Encapsulate(val2.bounds);
				val2.enabled = false;
			}
			Vector3 extents = ((Bounds)(ref val)).extents;
			releaseOffset = ((Vector3)(ref extents)).magnitude;
			((Component)this).transform.localScale = originalScale * 0.01f;
			if ((Object)(object)body != (Object)null)
			{
				bodyWasKinematic = body.isKinematic;
				body.isKinematic = true;
			}
			physGrabObject.OverrideDeactivate(0.1f);
		}

		private void Show()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			((Component)this).transform.localScale = originalScale;
			for (int i = 0; i < colliders.Length; i++)
			{
				if ((Object)(object)colliders[i] != (Object)null && i < colliderStates.Length)
				{
					colliders[i].enabled = colliderStates[i];
				}
			}
			if ((Object)(object)body != (Object)null)
			{
				body.isKinematic = bodyWasKinematic;
			}
			physGrabObject.OverrideDeactivateReset();
		}

		private static void RefreshLocalSlot(int playerKey, int slot)
		{
			if (playerKey == PlayerKeys.Local() && !((Object)(object)Inventory.instance == (Object)null))
			{
				InventorySpot spotByIndex = Inventory.instance.GetSpotByIndex(slot);
				if ((Object)(object)spotByIndex != (Object)null)
				{
					spotByIndex.UpdateUI();
				}
			}
		}
	}
	internal static class PocketReleaser
	{
		internal static void ReleaseLocalPockets()
		{
			int num = PlayerKeys.Local();
			PlayerPockets playerPockets = ((num == int.MinValue) ? null : PocketsApi.Find(num));
			if (playerPockets == null)
			{
				return;
			}
			int num2 = 0;
			for (int i = 0; i < playerPockets.Valuables.Length; i++)
			{
				ValuableObject val = playerPockets.Valuables[i];
				PocketedValuable pocketedValuable = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<PocketedValuable>() : null);
				if ((Object)(object)pocketedValuable != (Object)null)
				{
					pocketedValuable.RequestRelease(autoGrab: false, i - 1);
					num2++;
				}
			}
			if (num2 > 0)
			{
				PocketsPlugin.Logger.LogInfo((object)$"Pockets switched off: dropping {num2} stored valuable(s)");
			}
		}
	}
	internal sealed class PocketsRoomEvents : MonoBehaviourPunCallbacks
	{
		public override void OnJoinedRoom()
		{
			HostSettings.Publish();
		}

		public override void OnMasterClientSwitched(Player newMasterClient)
		{
			HostSettings.Publish();
		}

		public override void OnPlayerEnteredRoom(Player newPlayer)
		{
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			HostSettings.Publish();
			foreach (KeyValuePair<int, PlayerPockets> item in PocketsApi.Snapshot())
			{
				for (int i = 0; i < item.Value.Valuables.Length; i++)
				{
					ValuableObject val = item.Value.Valuables[i];
					PocketedValuable pocketedValuable = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<PocketedValuable>() : null);
					if ((Object)(object)pocketedValuable != (Object)null)
					{
						pocketedValuable.SendStateTo(newPlayer, item.Key, i);
					}
				}
			}
		}

		public override void OnPlayerLeftRoom(Player otherPlayer)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			foreach (KeyValuePair<int, PlayerPockets> item in PocketsApi.Snapshot())
			{
				PlayerAvatar val = PlayerKeys.Resolve(item.Key);
				if (!((Object)(object)val == (Object)null) && val.photonView.Owner != null && val.photonView.Owner.ActorNumber != otherPlayer.ActorNumber)
				{
					continue;
				}
				for (int i = 0; i < item.Value.Valuables.Length; i++)
				{
					ValuableObject val2 = item.Value.Valuables[i];
					if ((Object)(object)val2 != (Object)null)
					{
						PocketsApi.TryRemove(item.Key, i, ((Component)val2).transform.position);
					}
				}
			}
		}
	}
	internal static class PocketSync
	{
		internal static bool IsSizeAccepted(ValuableObject valuable)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected I4, but got Unknown
			if (SizePolicy.TryFromGameVolume((int)valuable.volumeType, out var size))
			{
				return SizePolicy.Accepts(size, ConfigurationController.MaxValuableSize);
			}
			return false;
		}

		internal static bool CanRelease(PocketedValuable pocketed, int slot, int playerKey, Vector3 position, PlayerAvatar? avatar, float maxDistanceFromPlayer, out string reason)
		{
			//IL_0054: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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_0088: 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)
			if ((Object)(object)avatar == (Object)null)
			{
				reason = "unknown player";
				return false;
			}
			if (avatar.isDisabled || avatar.deadSet)
			{
				reason = "the player is dead or disabled";
				return false;
			}
			if (!pocketed.IsPocketed || pocketed.PlayerKey != playerKey || pocketed.Slot != slot)
			{
				reason = "the valuable is not in that player's slot";
				return false;
			}
			if (float.IsNaN(position.x) || float.IsNaN(position.y) || float.IsNaN(position.z) || float.IsInfinity(position.x) || float.IsInfinity(position.y) || float.IsInfinity(position.z) || Vector3.Distance(position, ((Component)avatar).transform.position) > maxDistanceFromPlayer)
			{
				reason = "the drop position is invalid or too far from the player";
				return false;
			}
			reason = string.Empty;
			return true;
		}

		internal static bool CanStore(PocketedValuable pocketed, int slot, int playerKey, out string reason)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			ValuableObject valuable = pocketed.Valuable;
			if (!ConfigurationController.IsEnabled)
			{
				reason = "the mod is disabled";
				return false;
			}
			if (!SemiFunc.RunIsLevel())
			{
				reason = "not inside a level";
				return false;
			}
			PlayerAvatar val = PlayerKeys.Resolve(playerKey);
			if ((Object)(object)val == (Object)null)
			{
				reason = "unknown player";
				return false;
			}
			if (val.isDisabled || val.deadSet)
			{
				reason = "the player is dead or disabled";
				return false;
			}
			if (!PocketState.IsValidSlot(slot))
			{
				reason = $"invalid slot {slot}";
				return false;
			}
			if (pocketed.IsPocketed)
			{
				reason = "the valuable is already pocketed";
				return false;
			}
			if (valuable.committedToExtraction)
			{
				reason = "the valuable is committed to an extraction";
				return false;
			}
			if (!IsSizeAccepted(valuable))
			{
				reason = $"size {valuable.volumeType} is over the limit {ConfigurationController.MaxValuableSize}";
				return false;
			}
			PlayerPockets playerPockets = PocketsApi.Find(playerKey);
			if (playerPockets != null && playerPockets.State.IsOccupied(slot))
			{
				reason = $"slot {slot} is already occupied";
				return false;
			}
			PhysGrabObject physGrabObject = pocketed.PhysGrabObject;
			if ((Object)(object)val.physGrabber == (Object)null || !physGrabObject.playerGrabbing.Contains(val.physGrabber) || physGrabObject.playerGrabbing.Count != 1)
			{
				reason = "the valuable is not held only by the requesting player";
				return false;
			}
			reason = string.Empty;
			return true;
		}
	}
}
namespace Pockets.Domain
{
	public enum PocketSize
	{
		Tiny,
		Small,
		Medium,
		Big,
		Wide,
		Tall,
		VeryTall
	}
	internal sealed class PocketState
	{
		internal const int SlotCount = 3;

		internal const int NoValuable = int.MinValue;

		private readonly int[] slots = new int[3];

		internal int OccupiedCount
		{
			get
			{
				int num = 0;
				int[] array = slots;
				for (int i = 0; i < array.Length; i++)
				{
					if (array[i] != int.MinValue)
					{
						num++;
					}
				}
				return num;
			}
		}

		internal PocketState()
		{
			Clear();
		}

		internal static bool IsValidSlot(int slot)
		{
			if (slot >= 0)
			{
				return slot < 3;
			}
			return false;
		}

		internal bool IsOccupied(int slot)
		{
			if (IsValidSlot(slot))
			{
				return slots[slot] != int.MinValue;
			}
			return false;
		}

		internal int Get(int slot)
		{
			if (!IsValidSlot(slot))
			{
				return int.MinValue;
			}
			return slots[slot];
		}

		internal int FindSlot(int valuableKey)
		{
			if (valuableKey == int.MinValue)
			{
				return -1;
			}
			for (int i = 0; i < 3; i++)
			{
				if (slots[i] == valuableKey)
				{
					return i;
				}
			}
			return -1;
		}

		internal bool TryStore(int slot, int valuableKey)
		{
			if (!IsValidSlot(slot) || valuableKey == int.MinValue || slots[slot] != int.MinValue || FindSlot(valuableKey) != -1)
			{
				return false;
			}
			slots[slot] = valuableKey;
			return true;
		}

		internal bool TryRelease(int slot, out int valuableKey)
		{
			if (!IsOccupied(slot))
			{
				valuableKey = int.MinValue;
				return false;
			}
			valuableKey = slots[slot];
			slots[slot] = int.MinValue;
			return true;
		}

		internal int FirstFreeSlot()
		{
			for (int i = 0; i < 3; i++)
			{
				if (slots[i] == int.MinValue)
				{
					return i;
				}
			}
			return -1;
		}

		internal void Clear()
		{
			for (int i = 0; i < 3; i++)
			{
				slots[i] = int.MinValue;
			}
		}

		internal int[] Snapshot()
		{
			return (int[])slots.Clone();
		}
	}
	internal static class SizePolicy
	{
		internal static bool Accepts(PocketSize valuable, PocketSize maximum)
		{
			return valuable <= maximum;
		}

		internal static bool TryFromGameVolume(int gameVolume, out PocketSize size)
		{
			if (gameVolume < 0 || gameVolume > 6)
			{
				size = PocketSize.Tiny;
				return false;
			}
			size = (PocketSize)gameVolume;
			return true;
		}
	}
}
namespace Pockets.Api
{
	public sealed class PlayerDyingEventArgs
	{
		public int PlayerKey { get; }

		public bool Cancel { get; set; }

		public PlayerDyingEventArgs(int playerKey)
		{
			PlayerKey = playerKey;
		}
	}
	internal sealed class PlayerPockets
	{
		internal PocketState State { get; } = new PocketState();

		internal ValuableObject?[] Valuables { get; } = (ValuableObject?[])(object)new ValuableObject[3];

		internal void Clear()
		{
			State.Clear();
			for (int i = 0; i < Valuables.Length; i++)
			{
				Valuables[i] = null;
			}
		}
	}
	public readonly struct PocketEvent
	{
		public int PlayerKey { get; }

		public int Slot { get; }

		public int ValuableKey { get; }

		public ValuableObject? Valuable { get; }

		public PocketEvent(int playerKey, int slot, int valuableKey, ValuableObject? valuable)
		{
			PlayerKey = playerKey;
			Slot = slot;
			ValuableKey = valuableKey;
			Valuable = valuable;
		}
	}
	public static class PocketsApi
	{
		private static readonly Dictionary<int, PlayerPockets> Players = new Dictionary<int, PlayerPockets>();

		private static readonly HashSet<string> SlotValueRequirements = new HashSet<string>();

		internal static bool SlotValueRequired => SlotValueRequirements.Count > 0;

		public static event Action<PocketEvent>? Stored;

		public static event Action<PocketEvent>? Removed;

		public static event Action<PlayerDyingEventArgs>? PlayerDying;

		public static void RequireSlotValue(string requesterId)
		{
			if (!string.IsNullOrEmpty(requesterId))
			{
				SlotValueRequirements.Add(requesterId);
			}
		}

		public static void ReleaseSlotValueRequirement(string requesterId)
		{
			SlotValueRequirements.Remove(requesterId);
		}

		internal static List<KeyValuePair<int, PlayerPockets>> Snapshot()
		{
			return new List<KeyValuePair<int, PlayerPockets>>(Players);
		}

		public static IReadOnlyList<ValuableObject?> GetStored(int playerKey)
		{
			if (!Players.TryGetValue(playerKey, out PlayerPockets value))
			{
				return (IReadOnlyList<ValuableObject?>)(object)new ValuableObject[3];
			}
			return (IReadOnlyList<ValuableObject>)value.Valuables.Clone();
		}

		public static bool IsPocketed(ValuableObject valuable)
		{
			foreach (PlayerPockets value in Players.Values)
			{
				ValuableObject[] valuables = value.Valuables;
				for (int i = 0; i < valuables.Length; i++)
				{
					if ((Object)(object)valuables[i] == (Object)(object)valuable)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool TryRemove(int playerKey, int slot, Vector3? at = null)
		{
			//IL_006a: 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_006f: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return false;
			}
			PlayerPockets playerPockets = Find(playerKey);
			if (playerPockets == null || !PocketState.IsValidSlot(slot) || !playerPockets.State.IsOccupied(slot) || (Object)(object)playerPockets.Valuables[slot] == (Object)null)
			{
				return false;
			}
			PocketedValuable component = ((Component)playerPockets.Valuables[slot]).GetComponent<PocketedValuable>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			Vector3 position = (Vector3)(((??)at) ?? DefaultDropPosition(playerKey, component));
			component.BroadcastRelease(slot, playerKey, position, Quaternion.identity, autoGrab: false);
			return true;
		}

		private static Vector3 DefaultDropPosition(int playerKey, PocketedValuable pocketed)
		{
			//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_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)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar val = PlayerKeys.Resolve(playerKey);
			if (!((Object)(object)val != (Object)null))
			{
				return ((Component)pocketed).transform.position;
			}
			return ((Component)val).transform.position + Vector3.up * 0.5f;
		}

		internal static PlayerPockets GetOrCreate(int playerKey)
		{
			if (!Players.TryGetValue(playerKey, out PlayerPockets value))
			{
				value = new PlayerPockets();
				Players[playerKey] = value;
			}
			return value;
		}

		internal static PlayerPockets? Find(int playerKey)
		{
			if (!Players.TryGetValue(playerKey, out PlayerPockets value))
			{
				return null;
			}
			return value;
		}

		internal static void Forget(int playerKey, int slot)
		{
			PlayerPockets playerPockets = Find(playerKey);
			if (playerPockets != null && playerPockets.State.TryRelease(slot, out var _))
			{
				playerPockets.Valuables[slot] = null;
			}
		}

		internal static void ClearAll()
		{
			foreach (PlayerPockets value in Players.Values)
			{
				value.Clear();
			}
			Players.Clear();
		}

		internal static void RaiseStored(PocketEvent pocketEvent)
		{
			Raise(PocketsApi.Stored, pocketEvent, "Stored");
		}

		internal static void RaiseRemoved(PocketEvent pocketEvent)
		{
			Raise(PocketsApi.Removed, pocketEvent, "Removed");
		}

		internal static bool RaisePlayerDying(int playerKey)
		{
			PlayerDyingEventArgs e = new PlayerDyingEventArgs(playerKey);
			Raise(PocketsApi.PlayerDying, e, "PlayerDying");
			return e.Cancel;
		}

		private static void Raise<T>(Action<T>? handlers, T argument, string eventName)
		{
			if (handlers == null)
			{
				return;
			}
			Delegate[] invocationList = handlers.GetInvocationList();
			foreach (Delegate obj in invocationList)
			{
				try
				{
					((Action<T>)obj)(argument);
				}
				catch (Exception arg)
				{
					PocketsPlugin.Logger.LogError((object)$"A subscriber of PocketsApi.{eventName} threw: {arg}");
				}
			}
		}
	}
}