Decompiled source of Backpack v0.1.0

Backpack.dll

Decompiled an hour ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalCompanyInputUtils.Api;
using Microsoft.CodeAnalysis;
using ModMenu;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("BackpackTest")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Backpack")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+6ea35ec41208e1e869dc1a0b35b5bcd07f2e9d99")]
[assembly: AssemblyProduct("Backpack")]
[assembly: AssemblyTitle("Backpack")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 Backpack
{
	internal static class Hello
	{
		private static readonly Dictionary<ulong, float> Pending = new Dictionary<ulong, float>();

		private static readonly HashSet<ulong> Modded = new HashSet<ulong>();

		private static readonly List<ulong> Scratch = new List<ulong>();

		private static int _helloTries;

		private static float _nextHello;

		internal static readonly List<string> KickLog = new List<string>();

		internal static bool SuppressHello;

		internal static bool HostHasMod { get; private set; }

		internal static string Reason => "This lobby uses Backpack " + MajorMinor("0.1.0") + ". Install it from Thunderstore.";

		internal static void ClearSession()
		{
			if (Pending.Count != 0 || Modded.Count != 0 || HostHasMod || _helloTries != 0)
			{
				Pending.Clear();
				Modded.Clear();
				HostHasMod = false;
				_helloTries = 0;
				_nextHello = 0f;
			}
		}

		internal static IEnumerable<ulong> ModdedClients()
		{
			Scratch.Clear();
			foreach (ulong item in Modded)
			{
				if (item != 0L)
				{
					Scratch.Add(item);
				}
			}
			return Scratch;
		}

		private static string MajorMinor(string v)
		{
			string[] array = (v ?? "").Split('.');
			string text;
			if (array.Length < 2)
			{
				text = v;
				if (text == null)
				{
					return "";
				}
			}
			else
			{
				text = array[0] + "." + array[1];
			}
			return text;
		}

		internal static void OnClientConnected(ulong cid)
		{
			if (Net.IsHost && cid != 0L)
			{
				Pending[cid] = Time.realtimeSinceStartup;
				Plugin.V($"Backpack: client {cid} connected; waiting {Plugin.HelloTimeout.Value:F0} s for its hello");
			}
		}

		internal static void OnClientDisconnected(ulong cid)
		{
			Pending.Remove(cid);
			Modded.Remove(cid);
		}

		internal static void HostGotHello(ulong cid, string ver)
		{
			Pending.Remove(cid);
			if (MajorMinor(ver) != MajorMinor("0.1.0"))
			{
				Missing(cid, "has Backpack " + ver + ", the host 0.1.0");
				return;
			}
			bool num = Modded.Add(cid);
			Net.SendWelcome(cid);
			Net.SendFull(cid);
			if (num)
			{
				Plugin.Log.LogInfo((object)$"Backpack: client {cid} said hello ({ver})");
			}
		}

		private static void Missing(ulong cid, string why)
		{
			if (Plugin.MissingMod.Value == MissingModAction.Kick)
			{
				KickLog.Add($"{cid}: {why}");
				Plugin.Log.LogWarning((object)$"Backpack: kicking client {cid}: {why}");
				Net.NM.DisconnectClient(cid, Reason);
				return;
			}
			Plugin.Log.LogWarning((object)$"Backpack: client {cid} {why}; the backpack is locked for this lobby");
			HUDManager instance = HUDManager.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				instance.DisplayTip("Backpack locked", "A player joined without Backpack " + MajorMinor("0.1.0") + " (" + why + ").", true, false, "LC_Tip1");
			}
			Pack.HostLock();
		}

		internal static void Tick()
		{
			if (Net.IsHost)
			{
				if (Pending.Count == 0)
				{
					return;
				}
				float realtimeSinceStartup = Time.realtimeSinceStartup;
				Scratch.Clear();
				foreach (KeyValuePair<ulong, float> item in Pending)
				{
					if (realtimeSinceStartup - item.Value > Plugin.HelloTimeout.Value)
					{
						Scratch.Add(item.Key);
					}
				}
				{
					foreach (ulong item2 in Scratch)
					{
						Pending.Remove(item2);
						if (Net.NM.ConnectedClientsIds.Contains(item2))
						{
							Missing(item2, $"sent no hello in {Plugin.HelloTimeout.Value:F0} s");
						}
					}
					return;
				}
			}
			if (!HostHasMod && _helloTries < 5 && Net.NM.IsConnectedClient && !((Object)(object)GameNetworkManager.Instance?.localPlayerController == (Object)null) && !((Object)(object)StartOfRound.Instance == (Object)null) && !(Time.realtimeSinceStartup < _nextHello) && !SuppressHello)
			{
				_helloTries++;
				_nextHello = Time.realtimeSinceStartup + 3f;
				Net.SendHello();
				Plugin.V($"Backpack: hello sent ({_helloTries})");
			}
		}

		internal static void ClientGotWelcome(string ver)
		{
			if (!HostHasMod)
			{
				Plugin.Log.LogInfo((object)("Backpack: the host has Backpack " + ver));
			}
			HostHasMod = true;
		}
	}
	internal static class Local
	{
		internal enum Kind
		{
			None,
			Swap,
			QuickStow
		}

		internal const float StowSeconds = 0.5f;

		internal static Kind Pending;

		internal static int PendingHand;

		internal static int PendingSlot;

		internal static float PendingStart;

		internal static float PendingDue;

		internal static string Status = "";

		internal static float StatusUntil;

		private static float _regrabUntil;

		private static int _regrabSlot = -1;

		private static float _busyGraceUntil;

		private const float BusyGrace = 1.5f;

		private static readonly MethodInfo BeginGrabM = AccessTools.Method(typeof(PlayerControllerB), "BeginGrabObject", (Type[])null, (Type[])null);

		internal static PlayerControllerB Me
		{
			get
			{
				if (!((Object)(object)GameNetworkManager.Instance != (Object)null))
				{
					return null;
				}
				return GameNetworkManager.Instance.localPlayerController;
			}
		}

		internal static bool Busy => Pending != Kind.None;

		internal static float Progress
		{
			get
			{
				if (!Busy)
				{
					return 0f;
				}
				return Mathf.Clamp01((Time.time - PendingStart) / (PendingDue - PendingStart));
			}
		}

		internal static void Say(string s)
		{
			Status = s;
			StatusUntil = Time.time + 2.5f;
			Plugin.V("Backpack: " + s);
		}

		internal static string Check(int hand, int slot)
		{
			PlayerControllerB me = Me;
			string text = Pack.LocalBlocker(me);
			if (text != null)
			{
				return text;
			}
			if (Busy)
			{
				return "busy";
			}
			if (hand < 0 || hand >= me.ItemSlots.Length)
			{
				return "no hand slot selected";
			}
			if (slot < 0 || slot >= Pack.Unlocked)
			{
				if (slot >= 16)
				{
					return "no such slot";
				}
				return $"Row {slot / 4 + 1} is locked: ${Pack.Prices[slot / 4 - 1]} at the terminal";
			}
			GrabbableObject val = me.ItemSlots[hand];
			if ((Object)(object)val != (Object)null && val.itemProperties.twoHanded)
			{
				return "Too big for the pack";
			}
			if ((Object)(object)val == (Object)null && Pack.Of(Net.LocalIdx)[slot] == 0L)
			{
				return "Nothing to stow";
			}
			return null;
		}

		internal static bool BeginSwap(int hand, int slot)
		{
			string text = Check(hand, slot);
			if (text != null)
			{
				if (text != "busy")
				{
					Say(text);
				}
				return false;
			}
			Start(Kind.Swap, hand, slot);
			return true;
		}

		internal static bool BeginQuickStow()
		{
			PlayerControllerB me = Me;
			if ((Object)(object)me == (Object)null)
			{
				return false;
			}
			if (me.currentItemSlot < 0 || me.currentItemSlot >= me.ItemSlots.Length || (Object)(object)me.ItemSlots[me.currentItemSlot] == (Object)null)
			{
				Say("Nothing in your hand");
				return false;
			}
			int num = FreeSlot();
			if (num < 0)
			{
				Say("Pack full");
				return false;
			}
			string text = Check(me.currentItemSlot, num);
			if (text != null)
			{
				if (text != "busy")
				{
					Say(text);
				}
				return false;
			}
			Start(Kind.QuickStow, me.currentItemSlot, num);
			return true;
		}

		internal static int FreeSlot()
		{
			ulong[] array = Pack.Of(Net.LocalIdx);
			for (int i = 0; i < Pack.Unlocked; i++)
			{
				if (array[i] == 0L)
				{
					return i;
				}
			}
			return -1;
		}

		private static void Start(Kind k, int hand, int slot)
		{
			Pending = k;
			PendingHand = hand;
			PendingSlot = slot;
			PendingStart = Time.time;
			PendingDue = Time.time + 0.5f;
			_busyGraceUntil = 0f;
			Sfx.ZipStart(Me);
		}

		internal static void Cancel(string why)
		{
			if (Busy)
			{
				Pending = Kind.None;
				_regrabUntil = 0f;
				if (why != null)
				{
					Say(why);
				}
			}
		}

		internal static void Tick()
		{
			PlayerControllerB me = Me;
			if ((Object)(object)me == (Object)null || !Net.Online)
			{
				Pending = Kind.None;
				_regrabUntil = 0f;
				return;
			}
			if (Busy)
			{
				if (me.isPlayerDead || !me.isPlayerControlled || me.inTerminalMenu)
				{
					Cancel(null);
				}
				else if (Time.time >= PendingDue)
				{
					Kind pending = Pending;
					Pending = Kind.None;
					int num = PendingSlot;
					if (pending == Kind.QuickStow && Pack.Of(Net.LocalIdx)[num] != 0L)
					{
						num = FreeSlot();
					}
					string text = ((num < 0) ? "Pack full" : Check(PendingHand, num));
					if (text == "busy")
					{
						if (_busyGraceUntil == 0f)
						{
							_busyGraceUntil = Time.time + 1.5f;
						}
						if (Time.time < _busyGraceUntil)
						{
							Pending = pending;
							return;
						}
					}
					_busyGraceUntil = 0f;
					if (text != null)
					{
						Say(text);
						_regrabUntil = 0f;
					}
					else
					{
						GrabbableObject val = me.ItemSlots[PendingHand];
						if (_regrabUntil > 0f)
						{
							Plugin.V(string.Format("Backpack: auto-stow sends {0} ({1}) from hand slot {2} to pack slot {3}", ((Object)(object)val != (Object)null) ? val.itemProperties.itemName : "nothing", Pack.IdOf(val), PendingHand, num));
						}
						Pack.RequestSwap(PendingHand, num);
					}
				}
			}
			if (!(_regrabUntil > 0f))
			{
				return;
			}
			if (Time.time > _regrabUntil)
			{
				_regrabUntil = 0f;
			}
			else if (!Busy && _regrabSlot >= 0 && _regrabSlot < me.ItemSlots.Length && (Object)(object)me.ItemSlots[_regrabSlot] == (Object)null && !me.isGrabbingObjectAnimation)
			{
				_regrabUntil = 0f;
				Plugin.V($"Backpack: auto-stow regrab into hand slot {_regrabSlot}");
				try
				{
					BeginGrabM.Invoke(me, null);
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)$"Backpack: auto-stow regrab failed: {ex.InnerException ?? ex}");
				}
			}
		}

		internal static bool AutoStow(PlayerControllerB me)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.AutoStow.Value || (Object)(object)me != (Object)(object)Me)
			{
				return true;
			}
			if (_regrabUntil > 0f)
			{
				return false;
			}
			if (Busy || Pack.LocalBlocker(me) != null)
			{
				return true;
			}
			if (me.twoHanded || me.currentItemSlot < 0 || me.currentItemSlot >= me.ItemSlots.Length)
			{
				return true;
			}
			GrabbableObject[] itemSlots = me.ItemSlots;
			for (int i = 0; i < itemSlots.Length; i++)
			{
				if ((Object)(object)itemSlots[i] == (Object)null)
				{
					return true;
				}
			}
			GrabbableObject val = me.ItemSlots[me.currentItemSlot];
			if ((Object)(object)val == (Object)null || val.itemProperties.twoHanded)
			{
				return true;
			}
			RaycastHit val2 = default(RaycastHit);
			if (!Physics.Raycast(new Ray(((Component)me.gameplayCamera).transform.position, ((Component)me.gameplayCamera).transform.forward), ref val2, me.grabDistance, 1073742656) || ((Component)((RaycastHit)(ref val2)).collider).gameObject.layer == 8 || ((Component)((RaycastHit)(ref val2)).collider).tag != "PhysicsProp")
			{
				return true;
			}
			GrabbableObject component = ((Component)((RaycastHit)(ref val2)).collider).GetComponent<GrabbableObject>();
			if ((Object)(object)component == (Object)null || !component.grabbable || component.isHeld || component.isPocketed)
			{
				return true;
			}
			if (FreeSlot() < 0)
			{
				return true;
			}
			if (!BeginQuickStow())
			{
				return true;
			}
			_regrabSlot = me.currentItemSlot;
			_regrabUntil = Time.time + 0.5f + 2f;
			Plugin.V($"Backpack: auto-stow {val.itemProperties.itemName} ({Pack.IdOf(val)}) from hand slot {me.currentItemSlot} to pick up {component.itemProperties.itemName} ({Pack.IdOf(component)})");
			return false;
		}
	}
	internal static class Keys
	{
		private static InputAction _panel;

		private static InputAction _stow;

		internal static void Init()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_005c: Expected O, but got Unknown
			if (Plugin.InputUtilsLoaded)
			{
				FromInputUtils();
			}
			if (_panel == null || _stow == null)
			{
				InputActionMap val = new InputActionMap("Backpack");
				_panel = InputActionSetupExtensions.AddAction(val, "Backpack.Panel", (InputActionType)1, Plugin.PanelKey.Value, (string)null, (string)null, (string)null, (string)null);
				_stow = InputActionSetupExtensions.AddAction(val, "Backpack.QuickStow", (InputActionType)1, Plugin.StowKey.Value, (string)null, (string)null, (string)null, (string)null);
			}
			_panel.performed += delegate
			{
				OnPanel();
			};
			_stow.performed += delegate
			{
				OnStow();
			};
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void FromInputUtils()
		{
			_panel = BackpackInputs.Instance.Panel;
			_stow = BackpackInputs.Instance.QuickStow;
		}

		internal static void Enable(bool on)
		{
			if (_panel != null)
			{
				if (on)
				{
					_panel.Enable();
					_stow.Enable();
				}
				else
				{
					_panel.Disable();
					_stow.Disable();
				}
			}
		}

		private static bool Typing(PlayerControllerB p)
		{
			if (!((Object)(object)p == (Object)null) && !p.isTypingChat && !p.inTerminalMenu)
			{
				if ((Object)(object)p.quickMenuManager != (Object)null)
				{
					return p.quickMenuManager.isMenuOpen;
				}
				return false;
			}
			return true;
		}

		private static void OnPanel()
		{
			PlayerControllerB me = Local.Me;
			if (!((Object)(object)Panel.Instance == (Object)null))
			{
				if (Panel.Instance.IsOpen)
				{
					Panel.Instance.Close();
				}
				else if (!Typing(me) && me.isPlayerControlled && !me.isPlayerDead)
				{
					Panel.Instance.Open();
				}
			}
		}

		private static void OnStow()
		{
			PlayerControllerB me = Local.Me;
			if (!Typing(me) && me.isPlayerControlled && !me.isPlayerDead)
			{
				Local.BeginQuickStow();
			}
		}
	}
	internal class BackpackInputs : LcInputActions
	{
		internal static readonly BackpackInputs Instance = new BackpackInputs();

		[InputAction("<Keyboard>/b", Name = "Open backpack")]
		public InputAction Panel { get; set; }

		[InputAction("<Keyboard>/x", Name = "Quick stow")]
		public InputAction QuickStow { get; set; }
	}
	[HarmonyPatch]
	internal static class LocalPatches
	{
		[HarmonyPatch(typeof(StartOfRound), "OnEnable")]
		[HarmonyPostfix]
		private static void On()
		{
			Keys.Enable(on: true);
		}

		[HarmonyPatch(typeof(StartOfRound), "OnDisable")]
		[HarmonyPostfix]
		private static void Off()
		{
			Keys.Enable(on: false);
		}

		[HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")]
		[HarmonyPrefix]
		private static bool Grab(PlayerControllerB __instance)
		{
			if (!Panel.IsOpenNow)
			{
				return Local.AutoStow(__instance);
			}
			return false;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ActivateItem_performed")]
		[HarmonyPrefix]
		private static bool A1()
		{
			return !Panel.IsOpenNow;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ActivateItem_canceled")]
		[HarmonyPrefix]
		private static bool A2()
		{
			return !Panel.IsOpenNow;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ItemSecondaryUse_performed")]
		[HarmonyPrefix]
		private static bool A3()
		{
			return !Panel.IsOpenNow;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ItemTertiaryUse_performed")]
		[HarmonyPrefix]
		private static bool A4()
		{
			return !Panel.IsOpenNow;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")]
		[HarmonyPrefix]
		private static bool A5()
		{
			return !Panel.IsOpenNow;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Interact_performed")]
		[HarmonyPrefix]
		private static bool A6()
		{
			return !Panel.IsOpenNow;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Discard_performed")]
		[HarmonyPrefix]
		private static bool A7()
		{
			return !Panel.IsOpenNow;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "InspectItem_performed")]
		[HarmonyPrefix]
		private static bool A8()
		{
			return !Panel.IsOpenNow;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Emote1_performed")]
		[HarmonyPrefix]
		private static bool A9()
		{
			return !Panel.IsOpenNow;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Emote2_performed")]
		[HarmonyPrefix]
		private static bool A10()
		{
			return !Panel.IsOpenNow;
		}
	}
	internal static class MenuHooks
	{
		internal const string ModMenuGuid = "daniel.lethalcompany.modmenu";

		private const string Tab = "Backpack";

		private static string NotHosting()
		{
			if (Net.Online)
			{
				if (Net.IsHost)
				{
					return null;
				}
				return "host only";
			}
			return "not in a game";
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void Register()
		{
			string[] array = new string[4];
			for (int i = 0; i <= 3; i++)
			{
				array[i] = $"{i} ({4 * (i + 1)} slots)";
			}
			MenuApi.Choice("Backpack", "Backpack tier", array, (Func<int, string>)delegate(int t)
			{
				Pack.HostSetTier(t);
				return $"backpack tier {Pack.Tier} ({Pack.Unlocked} pack slots)";
			}, true, true, (Func<string>)NotHosting, "Sets it for the whole crew; saved with the ship.");
			MenuApi.Button("Backpack", "Reset tier", (Func<string>)delegate
			{
				Pack.HostSetTier(0);
				return "backpack tier reset to 0";
			}, true, true, (Func<string>)NotHosting, "Anything in a locked row spills at its owner's feet.");
			MenuApi.Button("Backpack", "Fill my pack with test scrap", (Func<string>)delegate
			{
				int num = Pack.HostFillOwnPack();
				return (num <= 0) ? null : $"filled {num} pack slot(s) with scrap";
			}, true, true, (Func<string>)delegate
			{
				object obj = NotHosting();
				if (obj == null)
				{
					if (!((Object)(object)GameNetworkManager.Instance?.localPlayerController == (Object)null))
					{
						if (Pack.Count(Net.LocalIdx) < Pack.Unlocked)
						{
							return (string)null;
						}
						return "pack is full";
					}
					obj = "not in a game";
				}
				return (string)obj;
			}, (string)null);
			MenuApi.Toggle("Backpack", "Sync overlay", (Func<bool>)(() => Overlay.Shown), (Func<bool, string>)delegate(bool on)
			{
				Overlay.Shown = on;
				return (!on) ? "sync overlay off" : "sync overlay on";
			}, false, false, (Func<string>)null, "Your pack next to the host's last state for you, to spot a desync.");
		}
	}
	internal static class Net
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static HandleNamedMessageDelegate <>9__17_0;

			public static HandleNamedMessageDelegate <>9__17_1;

			public static HandleNamedMessageDelegate <>9__17_2;

			public static HandleNamedMessageDelegate <>9__17_3;

			public static HandleNamedMessageDelegate <>9__17_4;

			public static HandleNamedMessageDelegate <>9__17_5;

			public static Converter<(int slot, ulong id), ulong> <>9__17_9;

			public static HandleNamedMessageDelegate <>9__17_6;

			public static HandleNamedMessageDelegate <>9__17_7;

			public static HandleNamedMessageDelegate <>9__17_8;

			public static Converter<(int slot, ulong id), ulong> <>9__29_0;

			internal void <Register>b__17_0(ulong s, FastBufferReader r)
			{
				if (IsHost)
				{
					string ver = default(string);
					((FastBufferReader)(ref r)).ReadValueSafe(ref ver, false);
					Hello.HostGotHello(s, ver);
				}
			}

			internal void <Register>b__17_1(ulong s, FastBufferReader r)
			{
				if (!IsHost)
				{
					string ver = default(string);
					((FastBufferReader)(ref r)).ReadValueSafe(ref ver, false);
					Hello.ClientGotWelcome(ver);
				}
			}

			internal void <Register>b__17_2(ulong s, FastBufferReader r)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: 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_0034: 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_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				if (IsHost)
				{
					byte op = default(byte);
					((FastBufferReader)(ref r)).ReadValueSafe<byte>(ref op, default(ForPrimitives));
					int a = default(int);
					((FastBufferReader)(ref r)).ReadValueSafe<int>(ref a, default(ForPrimitives));
					int b = default(int);
					((FastBufferReader)(ref r)).ReadValueSafe<int>(ref b, default(ForPrimitives));
					ulong expect = default(ulong);
					((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref expect, default(ForPrimitives));
					Pack.HostRequest(PlayerOf(s), s, (Pack.Op)op, a, b, expect);
				}
			}

			internal void <Register>b__17_3(ulong s, FastBufferReader r)
			{
				if (IsHost)
				{
					SendFull(s);
				}
			}

			internal void <Register>b__17_4(ulong s, FastBufferReader r)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: 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_0034: 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_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				if (!IsHost)
				{
					int p = default(int);
					((FastBufferReader)(ref r)).ReadValueSafe<int>(ref p, default(ForPrimitives));
					int hand = default(int);
					((FastBufferReader)(ref r)).ReadValueSafe<int>(ref hand, default(ForPrimitives));
					ulong handId = default(ulong);
					((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref handId, default(ForPrimitives));
					ulong[] array = new ulong[16];
					for (int i = 0; i < 16; i++)
					{
						((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref array[i], default(ForPrimitives));
					}
					Pack.ApplyState(p, array, hand, handId);
				}
			}

			internal void <Register>b__17_5(ulong s, FastBufferReader r)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: 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_0046: 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_0064: 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_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
				if (IsHost)
				{
					return;
				}
				int tier = default(int);
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref tier, default(ForPrimitives));
				bool locked = default(bool);
				((FastBufferReader)(ref r)).ReadValueSafe<bool>(ref locked, default(ForPrimitives));
				int[] array = new int[3];
				for (int i = 0; i < 3; i++)
				{
					((FastBufferReader)(ref r)).ReadValueSafe<int>(ref array[i], default(ForPrimitives));
				}
				int num = default(int);
				((FastBufferReader)(ref r)).ReadValueSafe<int>(ref num, default(ForPrimitives));
				Dictionary<int, ulong[]> dictionary = new Dictionary<int, ulong[]>();
				int key = default(int);
				for (int j = 0; j < num; j++)
				{
					((FastBufferReader)(ref r)).ReadValueSafe<int>(ref key, default(ForPrimitives));
					ulong[] array2 = new ulong[16];
					for (int k = 0; k < 16; k++)
					{
						((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref array2[k], default(ForPrimitives));
					}
					dictionary[key] = array2;
				}
				Pack.ApplyFull(tier, locked, array, dictionary);
			}

			internal void <Register>b__17_6(ulong s, FastBufferReader r)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: 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_003f: 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_0052: 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_0088: Unknown result type (might be due to invalid IL or missing references)
				//IL_008e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				if (!IsHost)
				{
					int num = default(int);
					((FastBufferReader)(ref r)).ReadValueSafe<int>(ref num, default(ForPrimitives));
					int num2 = default(int);
					((FastBufferReader)(ref r)).ReadValueSafe<int>(ref num2, default(ForPrimitives));
					List<(int, ulong)> list = new List<(int, ulong)>();
					int item = default(int);
					ulong item2 = default(ulong);
					for (int i = 0; i < num2; i++)
					{
						((FastBufferReader)(ref r)).ReadValueSafe<int>(ref item, default(ForPrimitives));
						((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref item2, default(ForPrimitives));
						list.Add((item, item2));
					}
					Vector3 val = default(Vector3);
					((FastBufferReader)(ref r)).ReadValueSafe(ref val);
					float yaw = default(float);
					((FastBufferReader)(ref r)).ReadValueSafe<float>(ref yaw, default(ForPrimitives));
					Plugin.V(string.Format("Backpack: drop message for p{0}: [{1}] at {2}", num, string.Join(",", list.ConvertAll(((int slot, ulong id) x) => x.id)), val));
					Pack.DropIds(num, list, val, yaw);
				}
			}

			internal ulong <Register>b__17_9((int slot, ulong id) x)
			{
				return x.id;
			}

			internal void <Register>b__17_7(ulong s, FastBufferReader r)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				if (IsHost)
				{
					int tier = default(int);
					((FastBufferReader)(ref r)).ReadValueSafe<int>(ref tier, default(ForPrimitives));
					Shop.HostBuy(s, tier);
				}
			}

			internal void <Register>b__17_8(ulong s, FastBufferReader r)
			{
				if (!IsHost)
				{
					string text = default(string);
					((FastBufferReader)(ref r)).ReadValueSafe(ref text, false);
					Shop.ShowNote(text);
				}
			}

			internal ulong <SendDrop>b__29_0((int slot, ulong id) x)
			{
				return x.id;
			}
		}

		internal const string HelloMsg = "Backpack.Hello";

		internal const string WelcomeMsg = "Backpack.Welcome";

		internal const string ReqMsg = "Backpack.Req";

		internal const string AskMsg = "Backpack.Ask";

		internal const string StateMsg = "Backpack.State";

		internal const string FullMsg = "Backpack.Full";

		internal const string DropMsg = "Backpack.Drop";

		internal const string BuyMsg = "Backpack.Buy";

		internal const string NoteMsg = "Backpack.Note";

		private static CustomMessagingManager _registeredOn;

		private static NetworkManager _callbacksOn;

		internal static NetworkManager NM => NetworkManager.Singleton;

		internal static bool Online
		{
			get
			{
				if ((Object)(object)NM != (Object)null && NM.IsListening)
				{
					return NM.CustomMessagingManager != null;
				}
				return false;
			}
		}

		internal static bool IsHost
		{
			get
			{
				if (Online)
				{
					return NM.IsServer;
				}
				return false;
			}
		}

		internal static int LocalIdx => (int)(GameNetworkManager.Instance?.localPlayerController?.playerClientId).GetValueOrDefault();

		internal static void Register()
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Expected O, but got Unknown
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Expected O, but got Unknown
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Expected O, but got Unknown
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Expected O, but got Unknown
			NetworkManager nM = NM;
			if ((Object)(object)nM == (Object)null)
			{
				return;
			}
			if ((Object)(object)_callbacksOn != (Object)(object)nM)
			{
				nM.OnClientConnectedCallback += Hello.OnClientConnected;
				nM.OnClientDisconnectCallback += Hello.OnClientDisconnected;
				_callbacksOn = nM;
			}
			if (nM.CustomMessagingManager == null || _registeredOn == nM.CustomMessagingManager)
			{
				return;
			}
			CustomMessagingManager customMessagingManager = nM.CustomMessagingManager;
			object obj = <>c.<>9__17_0;
			if (obj == null)
			{
				HandleNamedMessageDelegate val = delegate(ulong s, FastBufferReader r)
				{
					if (IsHost)
					{
						string ver = default(string);
						((FastBufferReader)(ref r)).ReadValueSafe(ref ver, false);
						Hello.HostGotHello(s, ver);
					}
				};
				<>c.<>9__17_0 = val;
				obj = (object)val;
			}
			customMessagingManager.RegisterNamedMessageHandler("Backpack.Hello", (HandleNamedMessageDelegate)obj);
			object obj2 = <>c.<>9__17_1;
			if (obj2 == null)
			{
				HandleNamedMessageDelegate val2 = delegate(ulong s, FastBufferReader r)
				{
					if (!IsHost)
					{
						string ver = default(string);
						((FastBufferReader)(ref r)).ReadValueSafe(ref ver, false);
						Hello.ClientGotWelcome(ver);
					}
				};
				<>c.<>9__17_1 = val2;
				obj2 = (object)val2;
			}
			customMessagingManager.RegisterNamedMessageHandler("Backpack.Welcome", (HandleNamedMessageDelegate)obj2);
			object obj3 = <>c.<>9__17_2;
			if (obj3 == null)
			{
				HandleNamedMessageDelegate val3 = delegate(ulong s, FastBufferReader r)
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0014: Unknown result type (might be due to invalid IL or missing references)
					//IL_0021: 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_0034: 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_0047: Unknown result type (might be due to invalid IL or missing references)
					//IL_004d: Unknown result type (might be due to invalid IL or missing references)
					if (IsHost)
					{
						byte op = default(byte);
						((FastBufferReader)(ref r)).ReadValueSafe<byte>(ref op, default(ForPrimitives));
						int a = default(int);
						((FastBufferReader)(ref r)).ReadValueSafe<int>(ref a, default(ForPrimitives));
						int b = default(int);
						((FastBufferReader)(ref r)).ReadValueSafe<int>(ref b, default(ForPrimitives));
						ulong expect = default(ulong);
						((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref expect, default(ForPrimitives));
						Pack.HostRequest(PlayerOf(s), s, (Pack.Op)op, a, b, expect);
					}
				};
				<>c.<>9__17_2 = val3;
				obj3 = (object)val3;
			}
			customMessagingManager.RegisterNamedMessageHandler("Backpack.Req", (HandleNamedMessageDelegate)obj3);
			object obj4 = <>c.<>9__17_3;
			if (obj4 == null)
			{
				HandleNamedMessageDelegate val4 = delegate(ulong s, FastBufferReader r)
				{
					if (IsHost)
					{
						SendFull(s);
					}
				};
				<>c.<>9__17_3 = val4;
				obj4 = (object)val4;
			}
			customMessagingManager.RegisterNamedMessageHandler("Backpack.Ask", (HandleNamedMessageDelegate)obj4);
			object obj5 = <>c.<>9__17_4;
			if (obj5 == null)
			{
				HandleNamedMessageDelegate val5 = delegate(ulong s, FastBufferReader r)
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0014: Unknown result type (might be due to invalid IL or missing references)
					//IL_0021: 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_0034: 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_005a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0060: Unknown result type (might be due to invalid IL or missing references)
					if (!IsHost)
					{
						int p = default(int);
						((FastBufferReader)(ref r)).ReadValueSafe<int>(ref p, default(ForPrimitives));
						int hand = default(int);
						((FastBufferReader)(ref r)).ReadValueSafe<int>(ref hand, default(ForPrimitives));
						ulong handId = default(ulong);
						((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref handId, default(ForPrimitives));
						ulong[] array = new ulong[16];
						for (int i = 0; i < 16; i++)
						{
							((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref array[i], default(ForPrimitives));
						}
						Pack.ApplyState(p, array, hand, handId);
					}
				};
				<>c.<>9__17_4 = val5;
				obj5 = (object)val5;
			}
			customMessagingManager.RegisterNamedMessageHandler("Backpack.State", (HandleNamedMessageDelegate)obj5);
			object obj6 = <>c.<>9__17_5;
			if (obj6 == null)
			{
				HandleNamedMessageDelegate val6 = delegate(ulong s, FastBufferReader r)
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0014: Unknown result type (might be due to invalid IL or missing references)
					//IL_0021: 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_0046: 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_0064: 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_0083: Unknown result type (might be due to invalid IL or missing references)
					//IL_0089: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
					//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
					if (!IsHost)
					{
						int tier = default(int);
						((FastBufferReader)(ref r)).ReadValueSafe<int>(ref tier, default(ForPrimitives));
						bool locked = default(bool);
						((FastBufferReader)(ref r)).ReadValueSafe<bool>(ref locked, default(ForPrimitives));
						int[] array = new int[3];
						for (int i = 0; i < 3; i++)
						{
							((FastBufferReader)(ref r)).ReadValueSafe<int>(ref array[i], default(ForPrimitives));
						}
						int num = default(int);
						((FastBufferReader)(ref r)).ReadValueSafe<int>(ref num, default(ForPrimitives));
						Dictionary<int, ulong[]> dictionary = new Dictionary<int, ulong[]>();
						int key = default(int);
						for (int j = 0; j < num; j++)
						{
							((FastBufferReader)(ref r)).ReadValueSafe<int>(ref key, default(ForPrimitives));
							ulong[] array2 = new ulong[16];
							for (int k = 0; k < 16; k++)
							{
								((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref array2[k], default(ForPrimitives));
							}
							dictionary[key] = array2;
						}
						Pack.ApplyFull(tier, locked, array, dictionary);
					}
				};
				<>c.<>9__17_5 = val6;
				obj6 = (object)val6;
			}
			customMessagingManager.RegisterNamedMessageHandler("Backpack.Full", (HandleNamedMessageDelegate)obj6);
			object obj7 = <>c.<>9__17_6;
			if (obj7 == null)
			{
				HandleNamedMessageDelegate val7 = delegate(ulong s, FastBufferReader r)
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0014: Unknown result type (might be due to invalid IL or missing references)
					//IL_0021: 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_003f: 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_0052: 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_0088: Unknown result type (might be due to invalid IL or missing references)
					//IL_008e: Unknown result type (might be due to invalid IL or missing references)
					//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
					//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
					if (!IsHost)
					{
						int num = default(int);
						((FastBufferReader)(ref r)).ReadValueSafe<int>(ref num, default(ForPrimitives));
						int num2 = default(int);
						((FastBufferReader)(ref r)).ReadValueSafe<int>(ref num2, default(ForPrimitives));
						List<(int, ulong)> list = new List<(int, ulong)>();
						int item = default(int);
						ulong item2 = default(ulong);
						for (int i = 0; i < num2; i++)
						{
							((FastBufferReader)(ref r)).ReadValueSafe<int>(ref item, default(ForPrimitives));
							((FastBufferReader)(ref r)).ReadValueSafe<ulong>(ref item2, default(ForPrimitives));
							list.Add((item, item2));
						}
						Vector3 val10 = default(Vector3);
						((FastBufferReader)(ref r)).ReadValueSafe(ref val10);
						float yaw = default(float);
						((FastBufferReader)(ref r)).ReadValueSafe<float>(ref yaw, default(ForPrimitives));
						Plugin.V(string.Format("Backpack: drop message for p{0}: [{1}] at {2}", num, string.Join(",", list.ConvertAll(((int slot, ulong id) x) => x.id)), val10));
						Pack.DropIds(num, list, val10, yaw);
					}
				};
				<>c.<>9__17_6 = val7;
				obj7 = (object)val7;
			}
			customMessagingManager.RegisterNamedMessageHandler("Backpack.Drop", (HandleNamedMessageDelegate)obj7);
			object obj8 = <>c.<>9__17_7;
			if (obj8 == null)
			{
				HandleNamedMessageDelegate val8 = delegate(ulong s, FastBufferReader r)
				{
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0014: Unknown result type (might be due to invalid IL or missing references)
					if (IsHost)
					{
						int tier = default(int);
						((FastBufferReader)(ref r)).ReadValueSafe<int>(ref tier, default(ForPrimitives));
						Shop.HostBuy(s, tier);
					}
				};
				<>c.<>9__17_7 = val8;
				obj8 = (object)val8;
			}
			customMessagingManager.RegisterNamedMessageHandler("Backpack.Buy", (HandleNamedMessageDelegate)obj8);
			object obj9 = <>c.<>9__17_8;
			if (obj9 == null)
			{
				HandleNamedMessageDelegate val9 = delegate(ulong s, FastBufferReader r)
				{
					if (!IsHost)
					{
						string text = default(string);
						((FastBufferReader)(ref r)).ReadValueSafe(ref text, false);
						Shop.ShowNote(text);
					}
				};
				<>c.<>9__17_8 = val9;
				obj9 = (object)val9;
			}
			customMessagingManager.RegisterNamedMessageHandler("Backpack.Note", (HandleNamedMessageDelegate)obj9);
			_registeredOn = customMessagingManager;
			Plugin.Log.LogInfo((object)"Backpack: messages registered.");
		}

		internal static int PlayerOf(ulong clientId)
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return -1;
			}
			if (clientId == 0L)
			{
				return LocalIdx;
			}
			if (instance.ClientPlayerList == null || !instance.ClientPlayerList.TryGetValue(clientId, out var value))
			{
				return -1;
			}
			return value;
		}

		internal unsafe static void SendHello()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			FastBufferWriter w = default(FastBufferWriter);
			((FastBufferWriter)(ref w))..ctor(64, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref w)).WriteValueSafe("0.1.0", false);
				ToHost("Backpack.Hello", w);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&w))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		internal unsafe static void SendReq(Pack.Op op, int a, int b, ulong expect)
		{
			//IL_002b: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (IsHost)
			{
				Pack.HostRequest(LocalIdx, 0uL, op, a, b, expect);
				return;
			}
			FastBufferWriter w = default(FastBufferWriter);
			((FastBufferWriter)(ref w))..ctor(32, (Allocator)2, -1);
			try
			{
				byte b2 = (byte)op;
				((FastBufferWriter)(ref w)).WriteValueSafe<byte>(ref b2, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref a, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref b, default(ForPrimitives));
				((FastBufferWriter)(ref w)).WriteValueSafe<ulong>(ref expect, default(ForPrimitives));
				ToHost("Backpack.Req", w);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&w))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		internal unsafe static void SendBuy(int tier)
		{
			//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)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			if (IsHost)
			{
				Shop.HostBuy(0uL, tier);
				return;
			}
			FastBufferWriter w = default(FastBufferWriter);
			((FastBufferWriter)(ref w))..ctor(8, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref w)).WriteValueSafe<int>(ref tier, default(ForPrimitives));
				ToHost("Backpack.Buy", w);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&w))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		internal unsafe static void SendAsk()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (IsHost)
			{
				return;
			}
			FastBufferWriter w = default(FastBufferWriter);
			((FastBufferWriter)(ref w))..ctor(4, (Allocator)2, -1);
			try
			{
				ToHost("Backpack.Ask", w);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&w))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void ToHost(string msg, FastBufferWriter w)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (Online)
			{
				NM.CustomMessagingManager.SendNamedMessage(msg, 0uL, w, (NetworkDelivery)3);
			}
		}

		internal unsafe static void SendWelcome(ulong to)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(64, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe("0.1.0", false);
				NM.CustomMessagingManager.SendNamedMessage("Backpack.Welcome", to, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		internal unsafe static void SendState(int player, ulong[] ids, int hand, ulong handId, ulong to = ulong.MaxValue)
		{
			//IL_001c: 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_002e: 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_0040: 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_005b: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHost)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(144, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref player, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref hand, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref handId, default(ForPrimitives));
				for (int i = 0; i < 16; i++)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref ids[i], default(ForPrimitives));
				}
				switch (to)
				{
				default:
					NM.CustomMessagingManager.SendNamedMessage("Backpack.State", to, val, (NetworkDelivery)3);
					break;
				case 0uL:
					break;
				case ulong.MaxValue:
				{
					foreach (ulong item in Hello.ModdedClients())
					{
						NM.CustomMessagingManager.SendNamedMessage("Backpack.State", item, val, (NetworkDelivery)3);
					}
					break;
				}
				}
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		internal unsafe static void SendFull(ulong to = ulong.MaxValue)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0067: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHost)
			{
				return;
			}
			Dictionary<int, ulong[]> dictionary = Pack.AllArrays();
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(16 + dictionary.Count * 132, (Allocator)2, 65536);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref Pack.Tier, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref Pack.Locked, default(ForPrimitives));
				for (int i = 0; i < 3; i++)
				{
					((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref Pack.Prices[i], default(ForPrimitives));
				}
				int count = dictionary.Count;
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref count, default(ForPrimitives));
				foreach (KeyValuePair<int, ulong[]> item in dictionary)
				{
					count = item.Key;
					((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref count, default(ForPrimitives));
					for (int j = 0; j < 16; j++)
					{
						((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref item.Value[j], default(ForPrimitives));
					}
				}
				switch (to)
				{
				default:
					NM.CustomMessagingManager.SendNamedMessage("Backpack.Full", to, val, (NetworkDelivery)4);
					break;
				case 0uL:
					break;
				case ulong.MaxValue:
				{
					foreach (ulong item2 in Hello.ModdedClients())
					{
						NM.CustomMessagingManager.SendNamedMessage("Backpack.Full", item2, val, (NetworkDelivery)4);
					}
					break;
				}
				}
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		internal unsafe static void SendDrop(int player, List<(int slot, ulong id)> items, Vector3 at, float yaw)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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)
			if (!IsHost)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(24 + 12 * items.Count, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref player, default(ForPrimitives));
				int count = items.Count;
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref count, default(ForPrimitives));
				foreach (var item in items)
				{
					var (num, num2) = item;
					((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
					((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref num2, default(ForPrimitives));
				}
				((FastBufferWriter)(ref val)).WriteValueSafe(ref at);
				((FastBufferWriter)(ref val)).WriteValueSafe<float>(ref yaw, default(ForPrimitives));
				List<ulong> list = new List<ulong>(Hello.ModdedClients());
				Plugin.V(string.Format("Backpack: sending drop of p{0} [{1}] to clients [{2}]", player, string.Join(",", items.ConvertAll(((int slot, ulong id) x) => x.id)), string.Join(",", list)));
				foreach (ulong item2 in list)
				{
					NM.CustomMessagingManager.SendNamedMessage("Backpack.Drop", item2, val, (NetworkDelivery)3);
				}
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}

		internal unsafe static void SendNote(ulong to, string text)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHost)
			{
				return;
			}
			if (to == 0L)
			{
				Shop.ShowNote(text);
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(256, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe(text, false);
				NM.CustomMessagingManager.SendNamedMessage("Backpack.Note", to, val, (NetworkDelivery)3);
			}
			finally
			{
				((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose();
			}
		}
	}
	internal class Overlay : MonoBehaviour
	{
		internal static bool Shown;

		private GUIStyle _style;

		private void OnGUI()
		{
			//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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			if (!Shown || !Net.Online)
			{
				return;
			}
			if (_style == null)
			{
				_style = new GUIStyle(GUI.skin.label)
				{
					fontSize = 13,
					richText = true
				};
			}
			int localIdx = Net.LocalIdx;
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			ulong[] array = Pack.Of(localIdx);
			ulong[] array2 = Pack.LastFromHost(localIdx);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(string.Format("<b>Backpack</b> tier {0} ({1} slots){2}  states {3} fulls {4} refused {5}\n", Pack.Tier, Pack.Unlocked, Pack.Locked ? " LOCKED" : "", Pack.StatesApplied, Pack.FullsApplied, Pack.Refused));
			int num = 0;
			for (int i = 0; i < 16; i++)
			{
				ulong num2 = ((array2 != null) ? array2[i] : 0);
				string text = "";
				if (array[i] != 0L)
				{
					GrabbableObject val2 = Pack.Resolve(array[i]);
					text = (((Object)(object)val2 == (Object)null) ? " GONE" : (((Object)(object)val2.playerHeldBy != (Object)(object)val) ? " not held" : ((!val2.isPocketed && (Object)(object)val.currentlyHeldObjectServer != (Object)(object)val2) ? " visible" : "")));
				}
				bool flag = (array2 == null || num2 == array[i]) && text.Length == 0;
				if (!flag)
				{
					num++;
				}
				string text2 = string.Format("{0,2}{1}: {2} | host {3}{4}", i, (i >= Pack.Unlocked) ? " (locked)" : "", array[i], (array2 == null) ? "-" : num2.ToString(), text);
				stringBuilder.Append(flag ? text2 : ("<color=#ff6060>" + text2 + "</color>")).Append('\n');
			}
			stringBuilder.Append((num == 0) ? "<color=#80ff80>in sync</color>" : $"<color=#ff6060>{num} slot(s) differ</color>");
			GUI.Box(new Rect(10f, 120f, 300f, 310f), GUIContent.none);
			GUI.Label(new Rect(16f, 124f, 290f, 304f), stringBuilder.ToString(), _style);
		}
	}
	internal static class Pack
	{
		internal enum Op : byte
		{
			Swap = 1,
			Move,
			Unpack,
			Drop
		}

		internal const int Slots = 16;

		internal const int RowSize = 4;

		internal const int MaxTier = 3;

		private static readonly Dictionary<int, ulong[]> Arrays = new Dictionary<int, ulong[]>();

		private static readonly HashSet<int> Dirty = new HashSet<int>();

		private static readonly Dictionary<int, ulong[]> HostView = new Dictionary<int, ulong[]>();

		internal static int Tier;

		internal static bool Locked;

		internal static readonly int[] Prices = new int[3] { 150, 300, 450 };

		internal static int Refused;

		internal static int StatesApplied;

		internal static int FullsApplied;

		internal static int Spills;

		internal static string LastRefusal = "";

		private static readonly MethodInfo SwitchToItemSlotM = AccessTools.Method(typeof(PlayerControllerB), "SwitchToItemSlot", (Type[])null, (Type[])null);

		private static readonly MethodInfo DropHeldItemM = AccessTools.Method(typeof(PlayerControllerB), "DropHeldItem", (Type[])null, (Type[])null);

		internal static int NextPrice
		{
			get
			{
				if (Tier >= 3)
				{
					return 0;
				}
				return Prices[Tier];
			}
		}

		internal static int Unlocked => 4 * (Tier + 1);

		internal static ulong[] LastFromHost(int p)
		{
			if (!HostView.TryGetValue(p, out var value))
			{
				return null;
			}
			return value;
		}

		internal static void ClearSession()
		{
			if (Arrays.Count == 0 && Tier == 0 && !Locked)
			{
				return;
			}
			Arrays.Clear();
			Dirty.Clear();
			HostView.Clear();
			Tier = 0;
			Locked = false;
			for (int i = 0; i < 3; i++)
			{
				if (Plugin.RowPrice[i] != null)
				{
					Prices[i] = Plugin.RowPrice[i].Value;
				}
			}
			Refused = (StatesApplied = (FullsApplied = (Spills = 0)));
		}

		internal static ulong[] Of(int p)
		{
			if (!Arrays.TryGetValue(p, out var value))
			{
				value = (Arrays[p] = new ulong[16]);
			}
			return value;
		}

		internal static Dictionary<int, ulong[]> AllArrays()
		{
			StartOfRound instance = StartOfRound.Instance;
			int num = (((Object)(object)instance != (Object)null && instance.allPlayerScripts != null) ? instance.allPlayerScripts.Length : 4);
			for (int i = 0; i < num; i++)
			{
				Of(i);
			}
			return Arrays;
		}

		internal static PlayerControllerB Player(int p)
		{
			StartOfRound instance = StartOfRound.Instance;
			if (!((Object)(object)instance != (Object)null) || instance.allPlayerScripts == null || p < 0 || p >= instance.allPlayerScripts.Length)
			{
				return null;
			}
			return instance.allPlayerScripts[p];
		}

		internal static GrabbableObject Resolve(ulong id)
		{
			if (id == 0L || !Net.Online || Net.NM.SpawnManager == null)
			{
				return null;
			}
			if (!Net.NM.SpawnManager.SpawnedObjects.TryGetValue(id, out var value) || !((Object)(object)value != (Object)null))
			{
				return null;
			}
			return ((Component)value).GetComponentInChildren<GrabbableObject>();
		}

		internal static ulong IdOf(GrabbableObject g)
		{
			if (!((Object)(object)g != (Object)null) || !((Object)(object)((NetworkBehaviour)g).NetworkObject != (Object)null))
			{
				return 0uL;
			}
			return ((NetworkBehaviour)g).NetworkObjectId;
		}

		internal static bool IsStowed(GrabbableObject g, out int player, out int slot)
		{
			player = (slot = -1);
			ulong num = IdOf(g);
			if (num == 0L)
			{
				return false;
			}
			foreach (KeyValuePair<int, ulong[]> array in Arrays)
			{
				int num2 = Array.IndexOf(array.Value, num);
				if (num2 >= 0)
				{
					player = array.Key;
					slot = num2;
					return true;
				}
			}
			return false;
		}

		internal static IEnumerable<GrabbableObject> Items(int p)
		{
			if (!Arrays.TryGetValue(p, out var value))
			{
				yield break;
			}
			ulong[] array = value;
			for (int i = 0; i < array.Length; i++)
			{
				GrabbableObject val = Resolve(array[i]);
				if ((Object)(object)val != (Object)null)
				{
					yield return val;
				}
			}
		}

		internal static int Count(int p)
		{
			if (!Arrays.TryGetValue(p, out var value))
			{
				return 0;
			}
			int num = 0;
			ulong[] array = value;
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] != 0L)
				{
					num++;
				}
			}
			return num;
		}

		internal static string LocalBlocker(PlayerControllerB me)
		{
			if (!Net.Online)
			{
				return "offline";
			}
			if (!Net.IsHost && !Hello.HostHasMod)
			{
				return "Host doesn't have Backpack";
			}
			if (Locked)
			{
				return "Backpack locked for this lobby";
			}
			if ((Object)(object)me == (Object)null || !me.isPlayerControlled || me.isPlayerDead)
			{
				return "not playing";
			}
			if (me.isGrabbingObjectAnimation || me.inSpecialInteractAnimation || me.activatingItem || me.inTerminalMenu)
			{
				return "busy";
			}
			return null;
		}

		internal static bool RequestSwap(int hand, int packSlot)
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			string text = LocalBlocker(val);
			if (text == null && (hand < 0 || hand >= val.ItemSlots.Length))
			{
				text = "no such hand slot";
			}
			if (text == null && (packSlot < 0 || packSlot >= Unlocked))
			{
				text = "pack slot locked";
			}
			GrabbableObject val2 = ((text == null) ? val.ItemSlots[hand] : null);
			if (text == null && (Object)(object)val2 != (Object)null && val2.itemProperties.twoHanded)
			{
				text = "Too big for the pack";
			}
			if (text == null && (Object)(object)val2 == (Object)null && Of(Net.LocalIdx)[packSlot] == 0L)
			{
				text = "both empty";
			}
			if (text != null)
			{
				Plugin.V($"Backpack: swap {hand}<->{packSlot} not sent: {text}");
				return false;
			}
			Net.SendReq(Op.Swap, hand, packSlot, IdOf(val2));
			return true;
		}

		internal static bool RequestStowHeld()
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val == (Object)null || val.currentItemSlot < 0 || val.currentItemSlot >= val.ItemSlots.Length)
			{
				return false;
			}
			int num = Array.IndexOf(Of(Net.LocalIdx), 0uL);
			if (num < 0 || num >= Unlocked)
			{
				Plugin.V("Backpack: pack full");
				return false;
			}
			return RequestSwap(val.currentItemSlot, num);
		}

		internal static bool RequestTake(int packSlot)
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val == (Object)null || val.currentItemSlot < 0 || val.currentItemSlot >= val.ItemSlots.Length)
			{
				return false;
			}
			return RequestSwap(val.currentItemSlot, packSlot);
		}

		internal static bool RequestMove(int from, int to)
		{
			if (LocalBlocker(GameNetworkManager.Instance?.localPlayerController) != null || from == to || from < 0 || to < 0 || from >= Unlocked || to >= Unlocked)
			{
				return false;
			}
			Net.SendReq(Op.Move, from, to, 0uL);
			return true;
		}

		internal static void HostRequest(int p, ulong sender, Op op, int a, int b, ulong expect)
		{
			switch (op)
			{
			case Op.Unpack:
				HostUnpack(p, sender);
				return;
			case Op.Drop:
				HostDropOne(p, sender, a, expect);
				return;
			}
			ulong[] next;
			int hand;
			ulong handId;
			string text = HostCheck(p, op, a, b, expect, out next, out hand, out handId);
			if (text != null)
			{
				Refused++;
				LastRefusal = text;
				Plugin.V($"Backpack: refused {op}({a},{b}) from player {p}: {text}");
				if (p >= 0)
				{
					Net.SendState(p, Of(p), -1, 0uL, sender);
				}
			}
			else
			{
				ApplyState(p, next, hand, handId);
				Net.SendState(p, next, hand, handId, ulong.MaxValue);
			}
		}

		private static void HostUnpack(int p, ulong sender)
		{
			PlayerControllerB val = Player(p);
			string text = (Locked ? "locked" : (((Object)(object)val == (Object)null || !val.isPlayerControlled || val.isPlayerDead) ? "player not alive" : ((Count(p) == 0) ? "pack empty" : null)));
			if (text != null)
			{
				Refused++;
				LastRefusal = text;
				Plugin.V($"Backpack: refused unpack from player {p}: {text}");
				if (p >= 0)
				{
					Net.SendState(p, Of(p), -1, 0uL, sender);
				}
				return;
			}
			ulong[] array = Of(p);
			List<(int, ulong)> list = new List<(int, ulong)>();
			for (int i = 0; i < 16; i++)
			{
				if (array[i] != 0L)
				{
					list.Add((i, array[i]));
				}
			}
			HostDrop(p, list);
			Net.SendState(p, Of(p), -1, 0uL, ulong.MaxValue);
		}

		private static void HostDropOne(int p, ulong sender, int slot, ulong expect)
		{
			PlayerControllerB val = Player(p);
			ulong[] array = Of(p);
			string text = (Locked ? "locked" : (((Object)(object)val == (Object)null || !val.isPlayerControlled || val.isPlayerDead) ? "player not alive" : ((slot < 0 || slot >= Unlocked) ? "pack slot locked" : ((array[slot] == 0L) ? "slot empty" : ((array[slot] != expect) ? $"slot {slot} holds {array[slot]}, asker saw {expect}" : null)))));
			if (text != null)
			{
				Refused++;
				LastRefusal = text;
				Plugin.V($"Backpack: refused drop of slot {slot} from player {p}: {text}");
				if (p >= 0)
				{
					Net.SendState(p, array, -1, 0uL, sender);
				}
			}
			else
			{
				HostDrop(p, new List<(int, ulong)> { (slot, expect) });
				Net.SendState(p, Of(p), -1, 0uL, ulong.MaxValue);
			}
		}

		internal static bool RequestDropOne(int slot)
		{
			if (LocalBlocker(GameNetworkManager.Instance?.localPlayerController) != null || slot < 0 || slot >= Unlocked || Of(Net.LocalIdx)[slot] == 0L)
			{
				return false;
			}
			Net.SendReq(Op.Drop, slot, 0, Of(Net.LocalIdx)[slot]);
			return true;
		}

		internal static bool RequestUnpack()
		{
			if (LocalBlocker(GameNetworkManager.Instance?.localPlayerController) != null || Count(Net.LocalIdx) == 0)
			{
				return false;
			}
			Net.SendReq(Op.Unpack, 0, 0, 0uL);
			return true;
		}

		private static string HostCheck(int p, Op op, int a, int b, ulong expect, out ulong[] next, out int hand, out ulong handId)
		{
			next = null;
			hand = -1;
			handId = 0uL;
			if (Locked)
			{
				return "locked";
			}
			PlayerControllerB val = Player(p);
			if ((Object)(object)val == (Object)null || !val.isPlayerControlled || val.isPlayerDead)
			{
				return "player not alive";
			}
			ulong[] array = Of(p);
			next = (ulong[])array.Clone();
			switch (op)
			{
			case Op.Move:
			{
				if (a < 0 || b < 0 || a >= Unlocked || b >= Unlocked || a == b)
				{
					return "bad slots";
				}
				ref ulong reference = ref next[a];
				ref ulong reference2 = ref next[b];
				ulong num = next[b];
				ulong num2 = next[a];
				reference = num;
				reference2 = num2;
				return null;
			}
			default:
				return "unknown op";
			case Op.Swap:
			{
				if (a < 0 || a >= val.ItemSlots.Length)
				{
					return "bad hand slot";
				}
				if (b < 0 || b >= Unlocked)
				{
					return "pack slot locked";
				}
				if (val.isGrabbingObjectAnimation)
				{
					return "mid-grab";
				}
				GrabbableObject val2 = val.ItemSlots[a];
				if (IdOf(val2) != expect)
				{
					return $"hand slot {a} holds {IdOf(val2)}, asker saw {expect}";
				}
				GrabbableObject val3 = Resolve(array[b]);
				if (array[b] != 0L && ((Object)(object)val3 == (Object)null || (Object)(object)val3.playerHeldBy != (Object)(object)val))
				{
					next[b] = 0uL;
					return "pack item gone";
				}
				if ((Object)(object)val2 == (Object)null && (Object)(object)val3 == (Object)null)
				{
					return "both empty";
				}
				if ((Object)(object)val2 != (Object)null)
				{
					if (val2.itemProperties.twoHanded)
					{
						return "two-handed";
					}
					if (!val2.isHeld || (Object)(object)val2.playerHeldBy != (Object)(object)val)
					{
						return "hand item not held by the player";
					}
					if ((Object)(object)val.ItemOnlySlot == (Object)(object)val2)
					{
						return "utility slot item";
					}
				}
				next[b] = IdOf(val2);
				hand = a;
				handId = array[b];
				return null;
			}
			}
		}

		internal static void HostSetTier(int tier)
		{
			if (!Net.IsHost)
			{
				return;
			}
			int num = Mathf.Clamp(tier, 0, 3);
			int num2 = 4 * (num + 1);
			if (num < Tier)
			{
				foreach (KeyValuePair<int, ulong[]> item in AllArrays())
				{
					ulong[] value = item.Value;
					List<(int, ulong)> list = new List<(int, ulong)>();
					for (int i = num2; i < 16; i++)
					{
						if (value[i] != 0L)
						{
							int num3 = Array.IndexOf(value, 0uL);
							if (num3 >= 0 && num3 < num2)
							{
								value[num3] = value[i];
								value[i] = 0uL;
							}
							else
							{
								list.Add((i, value[i]));
							}
						}
					}
					if (list.Count != 0)
					{
						HostDrop(item.Key, list);
					}
				}
			}
			Tier = num;
			Plugin.Log.LogInfo((object)$"Backpack: tier {Tier} ({Unlocked} pack slots)");
			Net.SendFull(ulong.MaxValue);
		}

		internal static void HostDrop(int p, List<(int slot, ulong id)> items)
		{
			//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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB val = Player(p);
			if (!((Object)(object)val == (Object)null))
			{
				Vector3 position = ((Component)val).transform.position;
				float y = ((Component)val).transform.eulerAngles.y;
				DropIds(p, items, position, y);
				Net.SendDrop(p, items, position, y);
			}
		}

		internal static void DropIds(int p, List<(int slot, ulong id)> items, Vector3 basePos, float yaw)
		{
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			PlayerControllerB val = Player(p);
			ulong[] array = Of(p);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			List<string> list = new List<string>();
			foreach (var item3 in items)
			{
				int item = item3.slot;
				ulong item2 = item3.id;
				for (int i = 0; i < 16; i++)
				{
					if (array[i] == item2)
					{
						array[i] = 0uL;
					}
				}
				GrabbableObject val2 = Resolve(item2);
				if ((Object)(object)val2 != (Object)null && val2.isHeld && (Object)(object)val2.playerHeldBy == (Object)null && Array.IndexOf(val.ItemSlots, val2) < 0)
				{
					Plugin.V($"Backpack: {item2} of p{p} was already discarded by vanilla's DiscardItemRpc; dropping it as p{p}'s");
					val2.playerHeldBy = val;
				}
				if ((Object)(object)val2 == (Object)null || !val2.isHeld || (Object)(object)val2.playerHeldBy != (Object)(object)val || Array.IndexOf(val.ItemSlots, val2) >= 0)
				{
					Plugin.V(string.Format("Backpack: not dropping {0} of p{1}: {2}", item2, p, ((Object)(object)val2 == (Object)null) ? "not found" : string.Format("held {0}, by {1}, in hotbar {2}", val2.isHeld, ((Object)(object)val2.playerHeldBy == (Object)null) ? "nobody" : val2.playerHeldBy.playerUsername, Array.IndexOf(val.ItemSlots, val2) >= 0)));
				}
				else if (DropOnRing(val, val2, item, itemsFall: true, disconnecting: false, basePos, basePos + Vector3.up * 1.6f, new Vector3(0f, yaw, 0f), val.isInHangarShipRoom, val.isInElevator))
				{
					val.carryWeight = Mathf.Clamp(val.carryWeight - (val2.itemProperties.weight - 1f), 1f, 10f);
					list.Add(item2.ToString());
				}
			}
			if (list.Count > 0)
			{
				Spills++;
				Sfx.Spill(val);
				Plugin.Log.LogInfo((object)string.Format("Backpack: {0} dropped {1} item(s) (unpack or locked rows) [{2}]", val.playerUsername, list.Count, string.Join(",", list)));
			}
		}

		private static bool DropOnRing(PlayerControllerB pl, GrabbableObject g, int s, bool itemsFall, bool disconnecting, Vector3 basePos, Vector3 camPos, Vector3 camRot, bool inShip, bool inElev)
		{
			//IL_0018: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: 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)
			float num = (float)s * 137.5f;
			float num2 = 0.35f + 0.06f * (float)s;
			Vector3 val = basePos + Vector3.up * 0.9f + Quaternion.Euler(0f, num, 0f) * Vector3.forward * num2;
			try
			{
				DropHeldItemM.Invoke(pl, new object[10]
				{
					g,
					itemsFall,
					disconnecting,
					basePos,
					val,
					(object)new Vector3(0f, num, 0f),
					camPos,
					camRot,
					inShip,
					inElev
				});
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)$"Backpack: dropping {((Object)g).name} failed: {ex.InnerException ?? ex}");
				return false;
			}
		}

		internal static int HostFillOwnPack()
		{
			//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_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			if (!Net.IsHost)
			{
				return 0;
			}
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)val == (Object)null || (Object)(object)instance == (Object)null || (Object)(object)instance.allItemsList == (Object)null)
			{
				return 0;
			}
			ulong[] array = Of(Net.LocalIdx);
			List<Item> list = new List<Item>();
			foreach (Item items in instance.allItemsList.itemsList)
			{
				if ((Object)(object)items != (Object)null && items.isScrap && !items.twoHanded && items.weight <= 1.1f && (Object)(object)items.spawnPrefab != (Object)null && (Object)(object)items.spawnPrefab.GetComponent<GrabbableObject>() != (Object)null)
				{
					list.Add(items);
				}
			}
			if (list.Count == 0)
			{
				return 0;
			}
			Transform val2 = (((Object)(object)RoundManager.Instance != (Object)null && (Object)(object)RoundManager.Instance.spawnedScrapContainer != (Object)null) ? RoundManager.Instance.spawnedScrapContainer : instance.propsContainer);
			int num = 0;
			List<NetworkObjectReference> list2 = new List<NetworkObjectReference>();
			List<int> list3 = new List<int>();
			for (int i = 0; i < Unlocked; i++)
			{
				if (array[i] == 0L)
				{
					Item val3 = list[Random.Range(0, list.Count)];
					GrabbableObject component = Object.Instantiate<GameObject>(val3.spawnPrefab, ((Component)val).transform.position + Vector3.up, Quaternion.identity, val2).GetComponent<GrabbableObject>();
					component.fallTime = 1f;
					component.hasHitGround = true;
					((NetworkBehaviour)component).NetworkObject.Spawn(false);
					int num2 = Mathf.Max(1, (int)((float)Random.Range(val3.minValue, val3.maxValue) * RoundManager.Instance.scrapValueMultiplier));
					component.SetScrapValue(num2);
					list2.Add(NetworkObjectReference.op_Implicit(((NetworkBehaviour)component).NetworkObject));
					list3.Add(num2);
					bool reswitch = false;
					TakeIntoPack(val, component, new List<int>(), ref reswitch);
					KeepPocketed(val, component);
					val.carryWeight = Mathf.Clamp(val.carryWeight + (val3.weight - 1f), 1f, 10f);
					array[i] = ((NetworkBehaviour)component).NetworkObjectId;
					num++;
				}
			}
			if (num > 0)
			{
				RoundManager.Instance.SyncScrapValuesClientRpc(list2.ToArray(), list3.ToArray());
				Net.SendFull(ulong.MaxValue);
			}
			return num;
		}

		internal static void HostLock()
		{
			if (!Locked)
			{
				Locked = true;
				Net.SendFull(ulong.MaxValue);
			}
		}

		internal static void ApplyState(int p, ulong[] ids, int hand, ulong handId)
		{
			PlayerControllerB val = Player(p);
			ulong[] array = Of(p);
			HostView[p] = (ulong[])ids.Clone();
			if ((Object)(object)val == (Object)null)
			{
				Array.Copy(ids, array, 16);
				return;
			}
			bool reswitch = false;
			bool flag = false;
			for (int i = 0; i < 16; i++)
			{
				if (ids[i] != array[i])
				{
					flag = true;
					break;
				}
			}
			List<int> list = new List<int>();
			for (int j = 0; j < 16; j++)
			{
				ulong num = ids[j];
				if (num != 0L && Array.IndexOf(array, num) < 0)
				{
					GrabbableObject val2 = Resolve(num);
					if ((Object)(object)val2 != (Object)null)
					{
						TakeIntoPack(val, val2, list, ref reswitch);
					}
					else
					{
						Plugin.V($"Backpack: state p{p}: {num} isn't spawned here yet; Tick attaches it when it is");
					}
				}
			}
			if (hand >= 0 && hand < val.ItemSlots.Length && handId != 0L && Array.IndexOf(array, handId) >= 0 && Array.IndexOf(ids, handId) < 0)
			{
				GrabbableObject val3 = Resolve(handId);
				if ((Object)(object)val3 != (Object)null)
				{
					val.ItemSlots[hand] = val3;
					val3.playerHeldBy = val;
					list.Add(hand);
					if (hand == val.currentItemSlot)
					{
						reswitch = true;
					}
				}
			}
			for (int k = 0; k < 16; k++)
			{
				ulong num2 = array[k];
				if (num2 != 0L && Array.IndexOf(ids, num2) < 0 && num2 != handId)
				{
					GrabbableObject val4 = Resolve(num2);
					if ((Object)(object)val4 != (Object)null && val4.isHeld && (Object)(object)val4.playerHeldBy == (Object)(object)val && Array.IndexOf(val.ItemSlots, val4) < 0)
					{
						Plugin.V($"Backpack: {num2} left p{p}'s pack (slot {k}) but is still pocketed here; waiting for its drop");
					}
				}
			}
			Array.Copy(ids, array, 16);
			if (reswitch)
			{
				Reselect(val);
			}
			for (int l = 0; l < ids.Length; l++)
			{
				GrabbableObject val5 = Resolve(ids[l]);
				if ((Object)(object)val5 != (Object)null)
				{
					KeepPocketed(val, val5);
				}
			}
			bool flag2 = (Object)(object)val == (Object)(object)GameNetworkManager.Instance?.localPlayerController;
			if (flag2)
			{
				RefreshIcons(val, list);
			}
			if (flag && (hand >= 0 || handId != 0L || list.Count > 0))
			{
				Sfx.Stowed(val, !flag2);
			}
			StatesApplied++;
			Plugin.V(string.Format("Backpack: state p{0} [{1}] hand {2}<-{3}; slots [{4}] current {5}", p, string.Join(",", ids), hand, handId, string.Join(",", Array.ConvertAll(val.ItemSlots, (GrabbableObject x) => IdOf(x))), val.currentItemSlot));
		}

		internal static void ApplyFull(int tier, bool locked, int[] prices, Dictionary<int, ulong[]> all)
		{
			Tier = Mathf.Clamp(tier, 0, 3);
			if (prices != null && prices.Length == 3)
			{
				Array.Copy(prices, Prices, 3);
			}
			Locked = locked;
			foreach (int item in new List<int>(Arrays.Keys))
			{
				if (!all.ContainsKey(item))
				{
					ApplyState(item, new ulong[16], -1, 0uL);
				}
			}
			foreach (KeyValuePair<int, ulong[]> item2 in all)
			{
				ApplyState(item2.Key, item2.Value, -1, 0uL);
			}
			foreach (KeyValuePair<int, ulong[]> item3 in all)
			{
				RecountRemoteWeight(item3.Key);
			}
			FullsApplied++;
			Plugin.V($"Backpack: full state, tier {Tier}, locked {Locked}, {all.Count} players");
		}

		private static void RecountRemoteWeight(int p)
		{
			PlayerControllerB val = Player(p);
			if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)GameNetworkManager.Instance?.localPlayerController || !val.isPlayerControlled)
			{
				return;
			}
			float num = 1f;
			GrabbableObject[] itemSlots = val.ItemSlots;
			foreach (GrabbableObject val2 in itemSlots)
			{
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.itemProperties != (Object)null)
				{
					num += val2.itemProperties.weight - 1f;
				}
			}
			if ((Object)(object)val.ItemOnlySlot != (Object)null && (Object)(object)val.ItemOnlySlot.itemProperties != (Object)null)
			{
				num += val.ItemOnlySlot.itemProperties.weight - 1f;
			}
			ulong[] array = Of(p);
			foreach (ulong num2 in array)
			{
				GrabbableObject val3 = ((num2 == 0L) ? null : Resolve(num2));
				if ((Object)(object)val3 != (Object)null && (Object)(object)val3.itemProperties != (Object)null)
				{
					num += val3.itemProperties.weight - 1f;
				}
			}
			val.carryWeight = Mathf.Clamp(num, 1f, 10f);
		}

		private static void TakeIntoPack(PlayerControllerB pl, GrabbableObject g, List<int> touched, ref bool reswitch)
		{
			for (int i = 0; i < pl.ItemSlots.Length; i++)
			{
				if (!((Object)(object)pl.ItemSlots[i] != (Object)(object)g))
				{
					pl.ItemSlots[i] = null;
					touched.Add(i);
					if (i == pl.currentItemSlot)
					{
						reswitch = true;
					}
				}
			}
			if ((Object)(object)pl.ItemOnlySlot == (Object)(object)g)
			{
				pl.ItemOnlySlot = null;
				if (pl.currentItemSlot == 50)
				{
					reswitch = true;
				}
			}
			if (!g.isHeld || (Object)(object)g.playerHeldBy != (Object)(object)pl)
			{
				g.isHeld = true;
				g.hasHitGround = false;
				g.playerHeldBy = pl;
				g.parentObject = (((NetworkBehaviour)pl).IsOwner ? pl.localItemHolder : pl.serverItemHolder);
				g.EnablePhysics(false);
				g.isInFactory = pl.isInsideFactory;
				g.isInElevator = pl.isInElevator;
				g.isInShipRoom = pl.isInHangarShipRoom;
				if (Net.IsHost)
				{
					g.heldByPlayerOnServer = true;
				}
			}
		}

		private static void KeepPocketed(PlayerControllerB pl, GrabbableObject g, bool meshes = true)
		{
			if ((Object)(object)pl.currentlyHeldObjectServer == (Object)(object)g)
			{
				return;
			}
			g.isPocketed = true;
			if (meshes)
			{
				g.EnableItemMeshes(false);
			}
			FlashlightItem val = (FlashlightItem)(object)((g is FlashlightItem) ? g : null);
			if (val == null || (!((GrabbableObject)val).isBeingUsed && !val.usingPlayerHelmetLight && !((Object)(object)pl.pocketedFlashlight == (Object)(object)val)))
			{
				return;
			}
			((GrabbableObject)val).isBeingUsed = false;
			val.usingPlayerHelmetLight = false;
			if ((Object)(object)val.flashlightBulb != (Object)null)
			{
				((Behaviour)val.flashlightBulb).enabled = false;
			}
			if ((Object)(object)val.flashlightBulbGlow != (Object)null)
			{
				((Behaviour)val.flashlightBulbGlow).enabled = false;
			}
			if ((Object)(object)pl.pocketedFlashlight == (Object)(object)val)
			{
				pl.pocketedFlashlight = null;
				if ((Object)(object)pl.helmetLight != (Object)null)
				{
					((Behaviour)pl.helmetLight).enabled = false;
				}
			}
		}

		private static void Reselect(PlayerControllerB pl)
		{
			try
			{
				SwitchToItemSlotM.Invoke(pl, new object[2] { pl.currentItemSlot, null });
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)$"Backpack: SwitchToItemSlot({pl.currentItemSlot}) failed: {ex.InnerException ?? ex}");
			}
		}

		private static void RefreshIcons(PlayerControllerB pl, List<int> slots)
		{
			HUDManager instance = HUDManager.Instance;
			if ((Object)(object)instance == (Object)null || instance.itemSlotIcons == null)
			{
				return;
			}
			foreach (int slot in slots)
			{
				if (slot >= 0 && slot < instance.itemSlotIcons.Length && slot < pl.ItemSlots.Length)
				{
					GrabbableObject val = pl.ItemSlots[slot];
					((Behaviour)instance.itemSlotIcons[slot]).enabled = (Object)(object)val != (Object)null;
					if ((Object)(object)val != (Object)null)
					{
						instance.itemSlotIcons[slot].sprite = val.itemProperties.itemIcon;
					}
				}
			}
		}

		internal static void Spill(PlayerControllerB pl, bool itemsFall, bool disconnecting, bool setInShip, bool setInElevator, Vector3 syncedPlayerPosition, Vector3 syncedPlayerCamPosition, Vector3 syncedPlayerCamRotation)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0075: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			int num = Array.IndexOf(StartOfRound.Instance.allPlayerScripts, pl);
			if (num < 0 || !Arrays.TryGetValue(num, out var value))
			{
				return;
			}
			bool flag = false;
			ulong[] array = value;
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] != 0L)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return;
			}
			bool flag2 = syncedPlayerPosition != default(Vector3);
			Vector3 val = (flag2 ? syncedPlayerPosition : ((Component)pl).transform.position);
			Vector3 camPos = ((flag2 && syncedPlayerCamPosition != default(Vector3)) ? syncedPlayerCamPosition : (val + Vector3.up * 1.6f));
			Vector3 camRot = (Vector3)(flag2 ? syncedPlayerCamRotation : new Vector3(0f, ((Component)pl).transform.eulerAngles.y, 0f));
			bool inShip = (flag2 ? setInShip : pl.isInHangarShipRoom);
			bool inElev = (flag2 ? setInElevator : pl.isInElevator);
			int num2 = 0;
			List<string> list = new List<string>();
			for (int j = 0; j < 16; j++)
			{
				GrabbableObject val2 = Resolve(value[j]);
				value[j] = 0uL;
				if (!((Object)(object)val2 == (Object)null) && DropOnRing(pl, val2, j, itemsFall, disconnecting, val, camPos, camRot, inShip, inElev))
				{
					num2++;
					list.Add($"{((NetworkBehaviour)val2).NetworkObjectId}");
				}
			}
			if (num2 > 0)
			{
				Spills++;
				if (!disconnecting)
				{
					Sfx.Spill(pl);
				}
				Plugin.Log.LogInfo((object)string.Format("Backpack: {0} spilled {1} pack item(s) ({2}, fall {3}) [{4}]", pl.playerUsername, num2, disconnecting ? "disconnect" : (flag2 ? "synced drop" : "drop"), itemsFall, string.Join(",", list)));
			}
		}

		internal static void SyncFlags(PlayerControllerB pl, bool inShipRoom, bool inElevator)
		{
			int num = Array.IndexOf(StartOfRound.Instance.allPlayerScripts, pl);
			if (num < 0)
			{
				return;
			}
			foreach (GrabbableObject item in Items(num))
			{
				if (!((Object)(object)item.playerHeldBy != (Object)(object)pl))
				{
					if (item.isInShipRoom != inShipRoom)
					{
						pl.SetItemInElevator(inShipRoom, inElevator, item);
					}
					item.isInElevator = inElevator;
					item.isInFactory = pl.isInsideFactory;
				}
			}
		}

		internal static void Tick()
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null)
			{
				return;
			}
			foreach (KeyValuePair<int, ulong[]> array in Arrays)
			{
				PlayerControllerB val = Player(array.Key);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				ulong[] value = array.Value;
				for (int i = 0; i < 16; i++)
				{
					if (value[i] == 0L)
					{
						continue;
					}
					GrabbableObject val2 = Resolve(value[i]);
					if ((Object)(object)val2 == (Object)null || !val2.isHeld || (Object)(object)val2.playerHeldBy != (Object)(object)val)
					{
						if (Net.IsHost)
						{
							Plugin.Log.LogWarning((object)string.Format("Backpack: p{0} slot {1}: item {2} {3}; clearing", array.Key, i, value[i], ((Object)(object)val2 == (Object)null) ? "is gone" : ("is no longer held by " + val.playerUsername)));
							value[i] = 0uL;
							Dirty.Add(array.Key);
						}
						else if ((Object)(object)val2 != (Object)null && (!val2.isHeld || (Object)(object)val2.playerHeldBy == (Object)null))
						{
							bool reswitch = false;
							TakeIntoPack(val, val2, new List<int>(), ref reswitch);
							KeepPocketed(val, val2);
						}
						continue;
					}
					if ((Object)(object)val.currentlyHeldObjectServer != (Object)(object)val2)
					{
						if (!val2.isPocketed)
						{
							KeepPocketed(val, val2);
						}
						else if (val2 is FlashlightItem)
						{
							KeepPocketed(val, val2, meshes: false);
						}
					}
					if (val2.isInShipRoom != val.isInHangarShipRoom)
					{
						val.SetItemInElevator(val.isInHangarShipRoom, val.isInElevator, val2);
					}
					val2.isInElevator = val.isInElevator;
					val2.isInFactory = val.isInsideFactory;
				}
			}
			if (Dirty.Count <= 0)
			{
				return;
			}
			foreach (int item in Dirty)
			{
				Net.SendState(item, Of(item), -1, 0uL, ulong.MaxValue);
			}
			Dirty.Clear();
		}
	}
	internal class Panel : MonoBehaviour
	{
		private class CellUi
		{
			public RectTransform Rt;

			public Image Bg;

			public Image Icon;

			public Image Progress;

			public Image Tint;

			public RawImage Model;

			public Outline Line;

			public TextMeshProUGUI Name;

			public TextMeshProUGUI Lock;

			public TextMeshProUGUI Price;
		}

		internal static Panel Instance;

		private static readonly Color Orange = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)128, (byte)40, byte.MaxValue));

		private static readonly Color OrangeDim = Color32.op_Implicit(new Color32((byte)150, (byte)80, (byte)30, byte.MaxValue));

		private static readonly Color Cream = Color32.op_Implicit(new Color32((byte)240, (byte)226, (byte)205, byte.MaxValue));

		private static readonly Color Tan = Color32.op_Implicit(new Color32((byte)205, (byte)165, (byte)120, byte.MaxValue));

		private static readonly Color Grey = Color32.op_Implicit(new Color32((byte)120, (byte)116, (byte)110, byte.MaxValue));

		private static readonly Color Back = Color32.op_Implicit(new Color32((byte)92, (byte)58, (byte)32, (byte)238));

		private static readonly Color CellBack = Color32.op_Implicit(Preview.Clear);

		private static readonly Color CellHover = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)190, (byte)120, (byte)40));

		private static readonly Color LockedBack = Color32.op_Implicit(new Color32((byte)52, (byte)40, (byte)30, (byte)235));

		private static readonly Color LockedLine = Color32.op_Implicit(new Color32((byte)110, (byte)88, (byte)66, byte.MaxValue));

		private static readonly Color Red = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)90, (byte)70, byte.MaxValue));

		private static readonly Color Fill = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)128, (byte)40, (byte)90));

		private static readonly Color TipBack = Color32.op_Implicit(new Color32((byte)64, (byte)40, (byte)22, (byte)248));

		private static readonly Color DropTint = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)90, (byte)70, (byte)70));

		private const float Cell = 104f;

		private const float Gap = 14f;

		private const float GridW = 458f;

		private const float GridH = 458f;

		private const float GridBottom = 250f;

		private const float LabelW = 420f;

		private RectTransform _root;

		private RectTransform _canvasRect;

		private RectTransform _unpack;

		private RectTransform _tip;

		private RectTransform _ghost;

		private RectTransform _back;

		private TMP_FontAsset _font;

		private TextMeshProUGUI _title;

		private TextMeshProUGUI _hint;

		private TextMeshProUGUI _hand;

		private TextMeshProUGUI _status;

		private TextMeshProUGUI _unpackText;

		private TextMeshProUGUI _tipText;

		private TextMeshProUGUI _hud;

		private TextMeshProUGUI _ghostText;

		private Image _unpackFill;

		private Image _ghostIcon;

		private RawImage _ghostModel;

		private RectTransform _ghostNote;

		private bool _outside;

		private readonly List<CellUi> _cells = new List<CellUi>();

		private readonly TextMeshProUGUI[] _rowLabels = (TextMeshProUGUI[])(object)new TextMeshProUGUI[4];

		private int _hover = -1;

		private int _press = -1;

		private Vector2 _pressAt;

		private bool _dragging;

		private bool _unpackHeld;

		private bool _lookWasDisabled;

		private float _unpackStart;

		internal static Vector2? TestCursor;

		internal static bool TestButton;

		private bool _testWasDown;

		private static Sprite _white;

		internal static bool IsOpenNow
		{
			get
			{
				if ((Object)(object)Instance != (Object)null)
				{
					return Instance.IsOpen;
				}
				return false;
			}
		}

		internal bool IsOpen { get; private set; }

		internal static void Create()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			GameObject val = new GameObject("Backpack.Canvas");
			Object.DontDestroyOnLoad((Object)(object)val);
			((Object)val).hideFlags = (HideFlags)61;
			Canvas obj = val.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 800;
			CanvasScaler obj2 = val.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			obj2.matchWidthOrHeight = 0.5f;
			Instance = val.AddComponent<Panel>();
			Instance._canvasRect = (RectTransform)val.transform;
			Instance.Build();
		}

		internal void Open()
		{
			if (IsOpen)
			{
				return;
			}
			PlayerControllerB me = Local.Me;
			if (!((Object)(object)me == (Object)null))
			{
				TMP_FontAsset val = FindFont();
				if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)_font)
				{
					SetFont(val);
				}
				IsOpen = true;
				((Component)_root).gameObject.SetActive(true);
				_lookWasDisabled = me.disableLookInput;
				me.disableLookInput = true;
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
				_press = -1;
				_dragging = false;
				_unpackHeld = false;
				Net.SendAsk();
				Redraw();
			}
		}

		internal void Close()
		{
			if (IsOpen)
			{
				IsOpen = false;
				((Component)_root).gameObject.SetActive(false);
				((Component)_tip).gameObject.SetActive(false);
				((Component)_ghost).gameObject.SetActive(false);
				PlayerControllerB me = Local.Me;
				if ((Object)(object)me != (Object)null)
				{
					me.disableLookInput = _lookWasDisabled;
				}
				if ((!((Object)(object)me != (Object)null) || !((Object)(object)me.quickMenuManager != (Object)null) || !me.quickMenuManager.isMenuOpen) && ((Object)(object)me == (Object)null || !me.inTerminalMenu))
				{
					Cursor.lockState = (CursorLockMode)1;
					Cursor.visible = false;
				}
			}
		}

		private void Update()
		{
			Local.Tick();
			UpdateHud();
			if (!IsOpen)
			{
				Preview.Tick(open: false, null, 0);
				return;
			}
			PlayerControllerB me = Local.Me;
			if ((Object)(object)me == (Object)null || !Net.Online || !me.isPlayerControlled || me.isPlayerDead || me.inTerminalMenu || me.isTypingChat || ((Object)(object)me.quickMenuManager != (Object)null && me.quickMenuManager.isMenuOpen))
			{
				Close();
				return;
			}
			me.disableLookInput = true;
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
			Mouse();
			Preview.Spin = (_dragging ? (-1) : _hover);
			Preview.Tick(open: true, Pack.Of(Net.LocalIdx), Pack.Unlocked);
			Redraw();
		}

		internal Vector2 ScreenPointOf(int i)
		{
			//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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			Rect rect;
			if (i == -2)
			{
				RectTransform back = _back;
				rect = _back.rect;
				float num = ((Rect)(ref rect)).xMax + 120f;
				rect = _back.rect;
				return RectTransformUtility.WorldToScreenPoint((Camera)null, ((Transform)back).TransformPoint(new Vector3(num, ((Rect)(ref rect)).center.y, 0f)));
			}
			RectTransform val = ((i < 0) ? _unpack : _cells[i].Rt);
			rect = val.rect;
			return RectTransformUtility.WorldToScreenPoint((Camera)null, ((Transform)val).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)));
		}

		private void Mouse()
		{
			//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_0056: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid I