Decompiled source of RustyHeathensQoL v1.0.1

RustyHeathensQoL.dll

Decompiled 3 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RustyHeathens.Automation;
using RustyHeathens.Backpacks;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Rusty Heathens QoL")]
[assembly: AssemblyDescription("Heathens' Haven quality-of-life features")]
[assembly: AssemblyCompany("RustyLaserGaming")]
[assembly: AssemblyProduct("Rusty Heathens QoL")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyVersion("1.0.1.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 RustyHeathens.Automation
{
	internal static class GroundStoreRules
	{
		internal static bool IsEligible(bool isPiece, int maxStackSize, bool isConsumable)
		{
			if (!isPiece && maxStackSize > 0)
			{
				if (!isConsumable)
				{
					return maxStackSize > 1;
				}
				return true;
			}
			return false;
		}
	}
	internal static class LiveAutoStore
	{
		private sealed class Request
		{
			internal ZDOID Drop;

			internal int Token;

			internal long Deadline;

			internal float Range;

			internal float NextAttempt;

			internal string Item = "unknown";

			internal string LastWait = "not_attempted";

			internal readonly List<ZDOID> Chests = new List<ZDOID>();

			internal Action<string> Log;

			internal Action<ZPackage> Report;
		}

		internal const string ReadyRpc = "RHSQOL_StoreReady_v3";

		internal const string JobRpc = "RHSQOL_StoreJob_v3";

		internal const string ResultRpc = "RHSQOL_StoreResult_v3";

		private static readonly Dictionary<ZDOID, Request> Pending = new Dictionary<ZDOID, Request>();

		private static readonly Dictionary<ZDOID, int> Seen = new Dictionary<ZDOID, int>();

		private static readonly MethodInfo LoadDrop = AccessTools.Method(typeof(ItemDrop), "Load", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo LoadChest = AccessTools.Method(typeof(Container), "CheckForChanges", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo RequestOwn = AccessTools.Method(typeof(ItemDrop), "RequestOwn", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo ChestAccess = AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null);

		private static bool paused;

		private static long Now
		{
			get
			{
				if (!((Object)(object)ZNet.instance == (Object)null))
				{
					return ZNet.instance.GetTime().Ticks;
				}
				return 0L;
			}
		}

		internal static void Clear()
		{
			Pending.Clear();
			Seen.Clear();
			paused = false;
		}

		private static ZNetView View(GameObject obj)
		{
			if (!((Object)(object)obj == (Object)null))
			{
				return obj.GetComponent<ZNetView>();
			}
			return null;
		}

		private static GameObject Instance(ZDOID id)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)ZNetScene.instance == (Object)null))
			{
				return ZNetScene.instance.FindInstance(id);
			}
			return null;
		}

		internal static void Handle(ZPackage pkg, Action<string> log, Action<ZPackage> report)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			if (pkg == null || paused || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			pkg.SetPos(0);
			Request request = new Request();
			request.Drop = pkg.ReadZDOID();
			request.Token = pkg.ReadInt();
			request.Deadline = pkg.ReadLong();
			request.Range = pkg.ReadSingle();
			int num = pkg.ReadInt();
			if (request.Token > 0 && !((ZDOID)(ref request.Drop)).IsNone() && num > 0 && num <= 64 && !(request.Range <= 0f) && !(request.Range > 64f) && StoreLease.IsLive(Now, request.Deadline) && (!Seen.TryGetValue(request.Drop, out var value) || value < request.Token) && (!Pending.TryGetValue(request.Drop, out var value2) || !StoreLease.IsLive(Now, value2.Deadline)))
			{
				for (int i = 0; i < num; i++)
				{
					request.Chests.Add(pkg.ReadZDOID());
				}
				request.Log = log;
				request.Report = report;
				if (Seen.Count > 4096 && Pending.Count == 0)
				{
					Seen.Clear();
				}
				Seen[request.Drop] = request.Token;
				Pending[request.Drop] = request;
				Tick();
			}
		}

		private unsafe static void Finish(Request request, string status, int amount, ZDOID chest)
		{
			//IL_0006: 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_007e: Expected O, but got Unknown
			//IL_0080: 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_003d: 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)
			Pending.Remove(request.Drop);
			if (status != "stored" && request.Log != null)
			{
				Action<string> log = request.Log;
				string[] obj = new string[6] { "RESULT drop=", null, null, null, null, null };
				ZDOID drop = request.Drop;
				obj[1] = ((object)(*(ZDOID*)(&drop))/*cast due to .constrained prefix*/).ToString();
				obj[2] = " item=";
				obj[3] = request.Item;
				obj[4] = " reason=";
				obj[5] = status;
				log(string.Concat(obj));
			}
			ZPackage val = new ZPackage();
			val.Write(request.Drop);
			val.Write(request.Token);
			val.Write(status);
			val.Write(amount);
			val.Write(chest);
			if (request.Report != null)
			{
				request.Report(val);
			}
		}

		internal unsafe static void Tick()
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: 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)
			if (paused || Pending.Count == 0)
			{
				return;
			}
			foreach (Request item in new List<Request>(Pending.Values))
			{
				if (!StoreLease.IsLive(Now, item.Deadline))
				{
					Finish(item, "expired:" + item.LastWait, 0, ZDOID.None);
				}
				else if (!(Time.realtimeSinceStartup < item.NextAttempt))
				{
					item.NextAttempt = Time.realtimeSinceStartup + 0.25f;
					try
					{
						TryStore(item);
					}
					catch (Exception ex)
					{
						paused = true;
						Action<string> log = item.Log;
						ZDOID drop = item.Drop;
						log("AUTOSTORE PAUSED drop=" + ((object)(*(ZDOID*)(&drop))/*cast due to .constrained prefix*/).ToString() + ": " + ex);
						Finish(item, "paused", 0, ZDOID.None);
						Pending.Clear();
						break;
					}
				}
			}
		}

		private static string AccessBlock(Container chest)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Invalid comparison between Unknown and I4
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Invalid comparison between Unknown and I4
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((int)chest.m_privacy == 0)
			{
				if ((Object)(object)localPlayer == (Object)null)
				{
					return "private_no_local_player";
				}
				if (ChestAccess == null)
				{
					return "private_access_api_missing";
				}
				if (!(bool)ChestAccess.Invoke(chest, new object[1] { localPlayer.GetPlayerID() }))
				{
					return "private_access_denied";
				}
			}
			else if ((int)chest.m_privacy != 1 && (int)chest.m_privacy != 2)
			{
				return "unknown_privacy";
			}
			if (chest.m_checkGuardStone)
			{
				if ((Object)(object)localPlayer == (Object)null)
				{
					return "ward_no_local_player";
				}
				if (!PrivateArea.CheckAccess(((Component)chest).transform.position, 0f, false, false))
				{
					return "ward_denied";
				}
			}
			return null;
		}

		private static void Count(SortedDictionary<string, int> reasons, string reason)
		{
			reasons.TryGetValue(reason, out var value);
			reasons[reason] = value + 1;
		}

		private static string Describe(SortedDictionary<string, int> reasons)
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, int> reason in reasons)
			{
				list.Add(reason.Key + "=" + reason.Value);
			}
			return string.Join(",", list.ToArray());
		}

		private unsafe static void TryStore(Request request)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Invalid comparison between Unknown and I4
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_047b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0480: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0502: Unknown result type (might be due to invalid IL or missing references)
			//IL_0507: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null && (Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer())
			{
				request.LastWait = "local_player_loading";
				return;
			}
			GameObject val = Instance(request.Drop);
			ItemDrop val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<ItemDrop>());
			ZNetView val3 = View(val);
			if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || !val3.IsValid())
			{
				request.LastWait = "drop_not_loaded";
				return;
			}
			if (LoadDrop == null || LoadChest == null || RequestOwn == null)
			{
				throw new InvalidOperationException("Vanilla load/ownership API unavailable.");
			}
			LoadDrop.Invoke(val2, null);
			ItemData itemData = val2.m_itemData;
			if (itemData == null || itemData.m_shared == null)
			{
				request.LastWait = "drop_data_unavailable";
				return;
			}
			request.Item = itemData.m_shared.m_name;
			if (itemData.m_stack <= 0)
			{
				Finish(request, "gone", 0, ZDOID.None);
				return;
			}
			if (!GroundStoreRules.IsEligible(val3.GetZDO().GetBool(ZDOVars.s_piece, false), itemData.m_shared.m_maxStackSize, (int)itemData.m_shared.m_itemType == 2))
			{
				Finish(request, "excluded", 0, ZDOID.None);
				return;
			}
			ZDOID val4 = ZDOID.None;
			float num = request.Range * request.Range;
			bool flag = false;
			SortedDictionary<string, int> reasons = new SortedDictionary<string, int>(StringComparer.Ordinal);
			foreach (ZDOID chest in request.Chests)
			{
				GameObject val5 = Instance(chest);
				if ((Object)(object)val5 == (Object)null)
				{
					flag = true;
					Count(reasons, "chest_not_loaded");
					continue;
				}
				Container component = val5.GetComponent<Container>();
				ZNetView val6 = View(val5);
				if ((Object)(object)component == (Object)null)
				{
					Count(reasons, "container_missing");
					continue;
				}
				if ((Object)(object)val6 == (Object)null || !val6.IsValid())
				{
					Count(reasons, "chest_view_invalid");
					continue;
				}
				if (!val6.IsOwner())
				{
					Count(reasons, "chest_not_owned");
					continue;
				}
				if (component.IsInUse() || val6.GetZDO().GetInt(ZDOVars.s_inUse, 0) != 0)
				{
					Count(reasons, "chest_in_use");
					continue;
				}
				if (!OwnerAutomation.EligibleChest(component, val6))
				{
					Count(reasons, "chest_excluded");
					continue;
				}
				string text = AccessBlock(component);
				if (text != null)
				{
					Count(reasons, text);
					continue;
				}
				Vector3 val7 = val5.transform.position - val.transform.position;
				float sqrMagnitude = ((Vector3)(ref val7)).sqrMagnitude;
				if (sqrMagnitude > request.Range * request.Range)
				{
					Count(reasons, "outside_range");
				}
				else if (!(sqrMagnitude > num))
				{
					LoadChest.Invoke(component, null);
					Inventory inventory = component.GetInventory();
					if (inventory == null)
					{
						Count(reasons, "inventory_unavailable");
						continue;
					}
					if (inventory.CountItems(itemData.m_shared.m_name, -1, true) <= 0)
					{
						Count(reasons, "no_matching_items");
						continue;
					}
					if (!inventory.CanAddItem(itemData, itemData.m_stack))
					{
						Count(reasons, "matching_chest_full");
						continue;
					}
					val4 = chest;
					num = sqrMagnitude;
				}
			}
			if (((ZDOID)(ref val4)).IsNone())
			{
				request.LastWait = "no_matching_chest:" + Describe(reasons);
				if (!flag)
				{
					Finish(request, request.LastWait, 0, ZDOID.None);
				}
			}
			else if (!val3.IsOwner())
			{
				RequestOwn.Invoke(val2, null);
				request.LastWait = "drop_owner_handoff";
			}
			else if (!val2.CanPickup(true))
			{
				request.LastWait = "vanilla_pickup_not_ready";
			}
			else if (StoreLease.IsLive(Now, request.Deadline))
			{
				int stack = itemData.m_stack;
				string lastWait = request.LastWait;
				request.LastWait = "transfer_rejected";
				if (OwnerAutomation.Store(request.Drop, val4, request.Range, request.Log, delegate(string reason)
				{
					request.LastWait = reason;
				}))
				{
					Finish(request, "stored", stack, val4);
				}
				else if (lastWait != request.LastWait && request.Log != null)
				{
					Action<string> log = request.Log;
					string[] obj = new string[6] { "TRANSFER WAIT drop=", null, null, null, null, null };
					ZDOID drop = request.Drop;
					obj[1] = ((object)(*(ZDOID*)(&drop))/*cast due to .constrained prefix*/).ToString();
					obj[2] = " item=";
					obj[3] = request.Item;
					obj[4] = " reason=";
					obj[5] = request.LastWait;
					log(string.Concat(obj));
				}
			}
		}
	}
	internal static class OwnerAutomation
	{
		internal const string ReadyRpc = "RHSQOL_AutomationReady_v2";

		internal const string JobRpc = "RHSQOL_AutomationJob_v2";

		private static readonly int BackpackMarker = StringExtensionMethods.GetStableHashCode("RHSQOL_RustyBackpack");

		private static readonly int GraveMarker = StringExtensionMethods.GetStableHashCode("RHSQOL_RustyBackpack_Grave");

		private static readonly Dictionary<ZDOID, float> NextJob = new Dictionary<ZDOID, float>();

		private static readonly HashSet<ZDOID> Blocked = new HashSet<ZDOID>();

		private static readonly List<ZDOID> EmptyDrops = new List<ZDOID>();

		private static bool emergencyPaused;

		private static readonly MethodInfo SaveContainer = AccessTools.Method(typeof(Container), "Save", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo LoadContainer = AccessTools.Method(typeof(Container), "CheckForChanges", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo SaveDrop = AccessTools.Method(typeof(ItemDrop), "Save", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo QueueOre = AccessTools.Method(typeof(Smelter), "QueueOre", new Type[2]
		{
			typeof(string),
			typeof(bool)
		}, (Type[])null);

		private static readonly MethodInfo SetFuel = AccessTools.Method(typeof(Smelter), "SetFuel", new Type[1] { typeof(float) }, (Type[])null);

		internal static void Clear()
		{
			NextJob.Clear();
			Blocked.Clear();
			EmptyDrops.Clear();
			emergencyPaused = false;
		}

		private static bool Owned(ZNetView view)
		{
			if ((Object)(object)view != (Object)null && view.IsValid())
			{
				return view.IsOwner();
			}
			return false;
		}

		private static ZNetView View(GameObject obj)
		{
			if (!((Object)(object)obj == (Object)null))
			{
				return obj.GetComponent<ZNetView>();
			}
			return null;
		}

		private static GameObject Instance(ZDOID id)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)ZNetScene.instance == (Object)null))
			{
				return ZNetScene.instance.FindInstance(id);
			}
			return null;
		}

		internal static bool EligibleChest(Container chest, ZNetView view)
		{
			if ((Object)(object)chest == (Object)null || !Owned(view) || (Object)(object)chest.m_wagon != (Object)null || chest.m_autoDestroyEmpty || chest.IsInUse())
			{
				return false;
			}
			ZDO zDO = view.GetZDO();
			if (zDO.GetInt(ZDOVars.s_inUse, 0) == 0 && !zDO.GetBool(BackpackMarker, false))
			{
				return !zDO.GetBool(GraveMarker, false);
			}
			return false;
		}

		internal unsafe static void Handle(ZPackage job, Action<string> log)
		{
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			if (emergencyPaused || job == null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			job.SetPos(0);
			int num = job.ReadInt();
			ZDOID val = job.ReadZDOID();
			if (Blocked.Contains(val))
			{
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (NextJob.TryGetValue(val, out var value) && realtimeSinceStartup < value)
			{
				return;
			}
			if (NextJob.Count > 4096)
			{
				NextJob.Clear();
			}
			NextJob[val] = realtimeSinceStartup + ((num == 1) ? 1.8f : 0.5f);
			try
			{
				switch (num)
				{
				case 1:
				{
					float num3 = job.ReadSingle();
					int maxFuel = Math.Max(0, Math.Min(20, job.ReadInt()));
					int maxOre = Math.Max(0, Math.Min(20, job.ReadInt()));
					int reserveFuel = Math.Max(0, job.ReadInt());
					int reserveOre = Math.Max(0, job.ReadInt());
					int num4 = job.ReadInt();
					if (num4 >= 0 && num4 <= 64 && !(num3 <= 0f) && !(num3 > 64f))
					{
						List<ZDOID> list = new List<ZDOID>();
						for (int i = 0; i < num4; i++)
						{
							list.Add(job.ReadZDOID());
						}
						Process(val, list, num3, maxFuel, maxOre, reserveFuel, reserveOre, log);
					}
					break;
				}
				case 2:
				{
					ZDOID val2 = job.ReadZDOID();
					float num2 = job.ReadSingle();
					if (!(num2 <= 0f) && !(num2 > 64f) && !Blocked.Contains(val2))
					{
						Store(val, val2, num2, log);
					}
					break;
				}
				}
			}
			catch (Exception ex)
			{
				Blocked.Add(val);
				emergencyPaused = true;
				ZDOID val3 = val;
				log("PAUSED object=" + ((object)(*(ZDOID*)(&val3))/*cast due to .constrained prefix*/).ToString() + ": " + ex);
			}
		}

		internal static void Tick()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			for (int num = EmptyDrops.Count - 1; num >= 0; num--)
			{
				GameObject val = Instance(EmptyDrops[num]);
				if ((Object)(object)val == (Object)null)
				{
					EmptyDrops.RemoveAt(num);
				}
				else
				{
					ZNetView val2 = View(val);
					ItemDrop component = val.GetComponent<ItemDrop>();
					if (!Owned(val2) || (Object)(object)component == (Object)null || component.m_itemData.m_stack != 0)
					{
						EmptyDrops.RemoveAt(num);
					}
					else
					{
						try
						{
							val2.Destroy();
							EmptyDrops.RemoveAt(num);
						}
						catch
						{
						}
					}
				}
			}
		}

		private static byte[] Bytes(Inventory inventory)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			inventory.Save(val);
			return val.GetArray();
		}

		private static bool Same(byte[] a, byte[] b)
		{
			if (a == null || b == null || a.Length != b.Length)
			{
				return false;
			}
			for (int i = 0; i < a.Length; i++)
			{
				if (a[i] != b[i])
				{
					return false;
				}
			}
			return true;
		}

		private static void Persist(Container chest, ZNetView view)
		{
			if (!Owned(view) || SaveContainer == null)
			{
				throw new InvalidOperationException("Container ownership/save unavailable.");
			}
			SaveContainer.Invoke(chest, null);
			if (!Same(Bytes(chest.GetInventory()), view.GetZDO().GetByteArray(ZDOVars.s_items, (byte[])null)))
			{
				throw new InvalidOperationException("Container inventory save was not verified.");
			}
		}

		private static void Restore(Container chest, ZNetView view, byte[] bytes)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Load(bytes);
			chest.GetInventory().Load(val);
			Persist(chest, view);
		}

		private static bool Feed(Smelter smelter, ZNetView station, Container chest, ZNetView chestView, string sharedName, string prefabName, int reserve, bool fuel)
		{
			if (!Owned(station) || !EligibleChest(chest, chestView))
			{
				return false;
			}
			Inventory inv = chest.GetInventory();
			int beforeCount = inv.CountItems(sharedName, -1, true);
			if (beforeCount <= reserve)
			{
				return false;
			}
			ItemData item = inv.GetItem(sharedName, -1, false);
			if (item == null)
			{
				return false;
			}
			ZDO zdo = station.GetZDO();
			float beforeFuel = zdo.GetFloat(ZDOVars.s_fuel, 0f);
			int beforeQueue = zdo.GetInt(ZDOVars.s_queued, 0);
			if (fuel ? (Math.Ceiling(beforeFuel) >= (double)smelter.m_maxFuel) : (beforeQueue >= smelter.m_maxOre))
			{
				return false;
			}
			if ((fuel && SetFuel == null) || (!fuel && QueueOre == null))
			{
				return false;
			}
			string slotKey = "item" + beforeQueue;
			string oldSlot = zdo.GetString(slotKey, "");
			bool oldCheated = zdo.GetBool(ZDOVars.s_cheatedQueued, false);
			byte[] chestBefore = Bytes(inv);
			float expectedFuel = Math.Min(smelter.m_maxFuel, beforeFuel + 1f);
			return TransferSafety.Commit(delegate
			{
				if (!Owned(station) || !EligibleChest(chest, chestView))
				{
					throw new InvalidOperationException("Ownership changed.");
				}
				if (fuel)
				{
					SetFuel.Invoke(smelter, new object[1] { expectedFuel });
				}
				else
				{
					QueueOre.Invoke(smelter, new object[2] { prefabName, item.m_cheated });
				}
			}, () => Owned(station) && ((!fuel) ? (zdo.GetInt(ZDOVars.s_queued, 0) == beforeQueue + 1 && zdo.GetString(slotKey, "") == prefabName) : (Math.Abs(zdo.GetFloat(ZDOVars.s_fuel, 0f) - expectedFuel) < 0.001f)), delegate
			{
				if (!EligibleChest(chest, chestView) || !inv.RemoveItem(item, 1))
				{
					throw new InvalidOperationException("Source removal was rejected.");
				}
				Persist(chest, chestView);
			}, () => Owned(station) && Owned(chestView) && inv.CountItems(sharedName, -1, true) == beforeCount - 1, delegate
			{
				if (!Owned(station))
				{
					throw new InvalidOperationException("Cannot restore a processor owned by another peer.");
				}
				if (fuel)
				{
					SetFuel.Invoke(smelter, new object[1] { beforeFuel });
				}
				else
				{
					zdo.Set(slotKey, oldSlot);
					zdo.Set(ZDOVars.s_queued, beforeQueue, false);
					zdo.Set(ZDOVars.s_cheatedQueued, oldCheated);
				}
			}, delegate
			{
				Restore(chest, chestView, chestBefore);
			});
		}

		private unsafe static void Process(ZDOID stationId, List<ZDOID> chests, float range, int maxFuel, int maxOre, int reserveFuel, int reserveOre, Action<string> log)
		{
			//IL_0000: 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_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Instance(stationId);
			ZNetView val2 = View(val);
			Smelter val3 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<Smelter>());
			if (!Owned(val2) || (Object)(object)val3 == (Object)null)
			{
				return;
			}
			int i = 0;
			int j = 0;
			for (int k = 0; k < chests.Count; k++)
			{
				GameObject val4 = Instance(chests[k]);
				Container val5 = (((Object)(object)val4 == (Object)null) ? null : val4.GetComponent<Container>());
				ZNetView val6 = View(val4);
				if (!EligibleChest(val5, val6))
				{
					continue;
				}
				Vector3 val7 = val4.transform.position - val.transform.position;
				if (((Vector3)(ref val7)).sqrMagnitude > range * range)
				{
					continue;
				}
				Player localPlayer = Player.m_localPlayer;
				string text = ProcessChestHandoff.AccessBlock(val5, ((Object)(object)localPlayer == (Object)null) ? 0 : localPlayer.GetPlayerID());
				if (text != null)
				{
					string[] obj = new string[6] { "PROCESS WAIT station=", null, null, null, null, null };
					ZDOID val8 = stationId;
					obj[1] = ((object)(*(ZDOID*)(&val8))/*cast due to .constrained prefix*/).ToString();
					obj[2] = " chest=";
					obj[3] = ((object)chests[k]/*cast due to .constrained prefix*/).ToString();
					obj[4] = " reason=";
					obj[5] = text;
					log(string.Concat(obj));
					continue;
				}
				if (LoadContainer == null)
				{
					throw new InvalidOperationException("Container refresh API unavailable.");
				}
				LoadContainer.Invoke(val5, null);
				if (!EligibleChest(val5, val6))
				{
					continue;
				}
				for (; i < maxFuel; i++)
				{
					if (!((Object)(object)val3.m_fuelItem != (Object)null))
					{
						break;
					}
					if (!Feed(val3, val2, val5, val6, val3.m_fuelItem.m_itemData.m_shared.m_name, null, reserveFuel, fuel: true))
					{
						break;
					}
				}
				if (val3.m_conversion == null)
				{
					continue;
				}
				for (int l = 0; l < val3.m_conversion.Count; l++)
				{
					if (j >= maxOre)
					{
						break;
					}
					ItemConversion val9 = val3.m_conversion[l];
					if (val9 == null || (Object)(object)val9.m_from == (Object)null)
					{
						continue;
					}
					for (; j < maxOre; j++)
					{
						if (!Feed(val3, val2, val5, val6, val9.m_from.m_itemData.m_shared.m_name, ((Object)((Component)val9.m_from).gameObject).name, reserveOre, fuel: false))
						{
							break;
						}
					}
				}
			}
			if (i + j > 0)
			{
				string[] obj2 = new string[6] { "FED owner-verified station=", null, null, null, null, null };
				ZDOID val8 = stationId;
				obj2[1] = ((object)(*(ZDOID*)(&val8))/*cast due to .constrained prefix*/).ToString();
				obj2[2] = " fuel+=";
				obj2[3] = i.ToString();
				obj2[4] = " input+=";
				obj2[5] = j.ToString();
				log(string.Concat(obj2));
			}
		}

		internal static bool Store(ZDOID dropId, ZDOID targetId, float range, Action<string> log)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return Store(dropId, targetId, range, log, null);
		}

		private static bool RejectStore(Action<string> rejected, string stage)
		{
			rejected?.Invoke("transfer_rejected:" + stage);
			return false;
		}

		private static bool SavedDropStack(ZNetView view, ItemData data, int expected)
		{
			if (!Owned(view))
			{
				return false;
			}
			ZDO zDO = view.GetZDO();
			byte[] byteArray = zDO.GetByteArray(ZDOVars.s_itemData, (byte[])null);
			if (byteArray == null || byteArray.Length <= 2)
			{
				return false;
			}
			ItemData obj = data.Clone();
			obj.m_stack = -1;
			ItemDrop.LoadFromZDO(obj, zDO, -1);
			return obj.m_stack == expected;
		}

		internal unsafe static bool Store(ZDOID dropId, ZDOID targetId, float range, Action<string> log, Action<string> rejected)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Invalid comparison between Unknown and I4
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Instance(dropId);
			GameObject val2 = Instance(targetId);
			ItemDrop drop = (((Object)(object)val == (Object)null) ? null : val.GetComponent<ItemDrop>());
			Container chest = (((Object)(object)val2 == (Object)null) ? null : val2.GetComponent<Container>());
			ZNetView dropView = View(val);
			ZNetView chestView = View(val2);
			if (!Owned(dropView))
			{
				return RejectStore(rejected, "drop_not_owned");
			}
			if (!EligibleChest(chest, chestView))
			{
				return RejectStore(rejected, "chest_unavailable");
			}
			if ((Object)(object)drop == (Object)null || SaveDrop == null)
			{
				return RejectStore(rejected, "drop_save_unavailable");
			}
			ItemData data = drop.m_itemData;
			if (data == null || data.m_shared == null)
			{
				return RejectStore(rejected, "drop_data_unavailable");
			}
			if (data.m_stack <= 0)
			{
				dropView.Destroy();
				return false;
			}
			if (!GroundStoreRules.IsEligible(dropView.GetZDO().GetBool(ZDOVars.s_piece, false), data.m_shared.m_maxStackSize, (int)data.m_shared.m_itemType == 2))
			{
				return RejectStore(rejected, "drop_excluded");
			}
			Vector3 val3 = val.transform.position - val2.transform.position;
			if (((Vector3)(ref val3)).sqrMagnitude > range * range)
			{
				return RejectStore(rejected, "outside_range");
			}
			Inventory inv = chest.GetInventory();
			string name = data.m_shared.m_name;
			int beforeCount = inv.CountItems(name, -1, true);
			int stack = data.m_stack;
			if (beforeCount <= 0 || !inv.CanAddItem(data, stack))
			{
				return RejectStore(rejected, "chest_match_or_capacity_changed");
			}
			byte[] before = Bytes(inv);
			string stage = "destination_ownership";
			if (!TransferSafety.Commit(delegate
			{
				if (!Owned(dropView) || !EligibleChest(chest, chestView))
				{
					throw new InvalidOperationException("Ownership changed.");
				}
				ItemData val5 = data.Clone();
				val5.m_stack = stack;
				stage = "destination_add";
				if (!inv.AddItem(val5))
				{
					throw new InvalidOperationException("Target chest rejected the stack.");
				}
				stage = "destination_save";
				Persist(chest, chestView);
			}, delegate
			{
				stage = "destination_verify";
				return Owned(chestView) && inv.CountItems(name, -1, true) == beforeCount + stack;
			}, delegate
			{
				stage = "source_ownership_or_count";
				if (!Owned(dropView) || data.m_stack != stack)
				{
					throw new InvalidOperationException("Ground stack changed.");
				}
				stage = "source_save";
				data.m_stack = 0;
				SaveDrop.Invoke(drop, null);
			}, delegate
			{
				stage = "source_verify";
				return Owned(dropView) && data.m_stack == 0 && SavedDropStack(dropView, data, 0);
			}, delegate
			{
				Restore(chest, chestView, before);
			}, delegate
			{
				if (!Owned(dropView))
				{
					throw new InvalidOperationException("Cannot restore another peer's ground item.");
				}
				data.m_stack = stack;
				SaveDrop.Invoke(drop, null);
				if (!SavedDropStack(dropView, data, stack))
				{
					throw new InvalidOperationException("Ground item rollback save was not verified.");
				}
			}))
			{
				return RejectStore(rejected, stage);
			}
			try
			{
				dropView.Destroy();
			}
			catch
			{
				EmptyDrops.Add(dropId);
			}
			string[] obj2 = new string[8]
			{
				"STORED owner-verified item=",
				name,
				" count=",
				stack.ToString(),
				" drop=",
				null,
				null,
				null
			};
			ZDOID val4 = dropId;
			obj2[5] = ((object)(*(ZDOID*)(&val4))/*cast due to .constrained prefix*/).ToString();
			obj2[6] = " chest=";
			val4 = targetId;
			obj2[7] = ((object)(*(ZDOID*)(&val4))/*cast due to .constrained prefix*/).ToString();
			log(string.Concat(obj2));
			return true;
		}
	}
	internal static class ProcessChestHandoff
	{
		internal const string ReadyRpc = "RHSQOL_ProcessChestReady_v1";

		internal const string JobRpc = "RHSQOL_ProcessChestHandoff_v1";

		internal const string ResultRpc = "RHSQOL_ProcessChestResult_v1";

		private static readonly Dictionary<ZDOID, int> Seen = new Dictionary<ZDOID, int>();

		private static readonly MethodInfo LoadChest = AccessTools.Method(typeof(Container), "CheckForChanges", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo SaveChest = AccessTools.Method(typeof(Container), "Save", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo CheckAccess = AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null);

		private static readonly FieldInfo WardAreas = AccessTools.Field(typeof(PrivateArea), "m_allAreas");

		private static readonly MethodInfo WardEnabled = AccessTools.Method(typeof(PrivateArea), "IsEnabled", Type.EmptyTypes, (Type[])null);

		private static readonly MethodInfo WardInside = AccessTools.Method(typeof(PrivateArea), "IsInside", new Type[2]
		{
			typeof(Vector3),
			typeof(float)
		}, (Type[])null);

		private static readonly MethodInfo WardPermitted = AccessTools.Method(typeof(PrivateArea), "IsPermitted", new Type[1] { typeof(long) }, (Type[])null);

		internal static void Clear()
		{
			Seen.Clear();
		}

		internal static string AccessBlock(Container chest, long playerId)
		{
			//IL_0010: 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_005b: Invalid comparison between Unknown and I4
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Invalid comparison between Unknown and I4
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)chest == (Object)null)
			{
				return "container_missing";
			}
			if ((int)chest.m_privacy == 0)
			{
				if (playerId == 0L || CheckAccess == null)
				{
					return "private_access_unavailable";
				}
				if (!(bool)CheckAccess.Invoke(chest, new object[1] { playerId }))
				{
					return "private_access_denied";
				}
			}
			else if ((int)chest.m_privacy != 1 && (int)chest.m_privacy != 2)
			{
				return "unknown_privacy";
			}
			if (!chest.m_checkGuardStone)
			{
				return null;
			}
			if (WardAreas == null || WardEnabled == null || WardInside == null || WardPermitted == null)
			{
				return "ward_access_unavailable";
			}
			if (!(WardAreas.GetValue(null) is IEnumerable enumerable))
			{
				return "ward_access_unavailable";
			}
			bool flag = false;
			foreach (object item in enumerable)
			{
				PrivateArea val = (PrivateArea)((item is PrivateArea) ? item : null);
				if (!((Object)(object)val == (Object)null) && (bool)WardEnabled.Invoke(val, null) && (bool)WardInside.Invoke(val, new object[2]
				{
					((Component)chest).transform.position,
					0f
				}))
				{
					if (playerId == 0L)
					{
						return "ward_access_unavailable";
					}
					Piece component = ((Component)val).GetComponent<Piece>();
					if ((Object)(object)component == (Object)null)
					{
						return "ward_access_unavailable";
					}
					if (component.GetCreator() == playerId || (bool)WardPermitted.Invoke(val, new object[1] { playerId }))
					{
						return null;
					}
					flag = true;
				}
			}
			if (!flag)
			{
				return null;
			}
			return "ward_denied";
		}

		internal static bool HasInputs(Smelter smelter, ZDO station, Inventory inv, int reserveFuel, int reserveOre)
		{
			if ((Object)(object)smelter == (Object)null || station == null || inv == null)
			{
				return false;
			}
			if ((Object)(object)smelter.m_fuelItem != (Object)null && smelter.m_fuelItem.m_itemData != null && Math.Ceiling(station.GetFloat(ZDOVars.s_fuel, 0f)) < (double)smelter.m_maxFuel && inv.CountItems(smelter.m_fuelItem.m_itemData.m_shared.m_name, -1, true) > reserveFuel)
			{
				return true;
			}
			if (station.GetInt(ZDOVars.s_queued, 0) >= smelter.m_maxOre || smelter.m_conversion == null)
			{
				return false;
			}
			foreach (ItemConversion item in smelter.m_conversion)
			{
				if (item != null && (Object)(object)item.m_from != (Object)null && item.m_from.m_itemData != null && inv.CountItems(item.m_from.m_itemData.m_shared.m_name, -1, true) > reserveOre)
				{
					return true;
				}
			}
			return false;
		}

		private static bool ReadyToGrant(Container chest, ZNetView chestView, ZNetView stationView, long recipient, long playerId, float range, long deadline)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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)
			if (StoreLease.IsLive(ZNet.instance.GetTime().Ticks, deadline) && OwnerAutomation.EligibleChest(chest, chestView) && stationView.IsValid() && stationView.GetZDO().GetOwner() == recipient)
			{
				Vector3 val = ((Component)stationView).transform.position - ((Component)chestView).transform.position;
				if (((Vector3)(ref val)).sqrMagnitude <= range * range)
				{
					return AccessBlock(chest, playerId) == null;
				}
			}
			return false;
		}

		internal static string Handle(ZPackage pkg, Action<long, ZDOID> replicate, out ZDOID chestId, out int token)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Expected O, but got Unknown
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			chestId = ZDOID.None;
			token = 0;
			try
			{
				if (pkg == null || (Object)(object)ZNet.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null)
				{
					return "not_loaded";
				}
				pkg.SetPos(0);
				ZDOID val = pkg.ReadZDOID();
				chestId = pkg.ReadZDOID();
				token = pkg.ReadInt();
				long num = pkg.ReadLong();
				long num2 = pkg.ReadLong();
				long playerId = pkg.ReadLong();
				float num3 = pkg.ReadSingle();
				int num4 = pkg.ReadInt();
				int num5 = pkg.ReadInt();
				long ticks = ZNet.instance.GetTime().Ticks;
				if (((ZDOID)(ref val)).IsNone() || ((ZDOID)(ref chestId)).IsNone() || val == chestId || token <= 0 || num2 == 0L || float.IsNaN(num3) || float.IsInfinity(num3) || num3 <= 0f || num3 > 64f || num4 < 0 || num4 > 999 || num5 < 0 || num5 > 999 || !StoreLease.IsLive(ticks, num) || num - ticks > 100000000)
				{
					return "invalid_or_expired";
				}
				if (Seen.TryGetValue(chestId, out var value) && value >= token)
				{
					return "replayed";
				}
				if (Seen.Count > 4096)
				{
					Seen.Clear();
				}
				Seen[chestId] = token;
				GameObject val2 = ZNetScene.instance.FindInstance(val);
				GameObject val3 = ZNetScene.instance.FindInstance(chestId);
				ZNetView val4 = (((Object)(object)val2 == (Object)null) ? null : val2.GetComponent<ZNetView>());
				ZNetView val5 = (((Object)(object)val3 == (Object)null) ? null : val3.GetComponent<ZNetView>());
				Smelter val6 = (((Object)(object)val2 == (Object)null) ? null : val2.GetComponent<Smelter>());
				Container val7 = (((Object)(object)val3 == (Object)null) ? null : val3.GetComponent<Container>());
				if ((Object)(object)val4 == (Object)null || !val4.IsValid() || (Object)(object)val6 == (Object)null)
				{
					return "station_not_loaded";
				}
				if (val4.GetZDO().GetOwner() != num2)
				{
					return "station_owner_changed";
				}
				if (!OwnerAutomation.EligibleChest(val7, val5))
				{
					return "chest_unavailable";
				}
				if ((Object)(object)((Component)val7).GetComponent<TombStone>() != (Object)null || ((Object)val3).name.IndexOf("private", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return "chest_excluded";
				}
				if (val5.GetZDO().GetOwner() == num2)
				{
					return "already_owned";
				}
				Vector3 val8 = val2.transform.position - val3.transform.position;
				if (((Vector3)(ref val8)).sqrMagnitude > num3 * num3)
				{
					return "outside_range";
				}
				string text = AccessBlock(val7, playerId);
				if (text != null)
				{
					return text;
				}
				if (LoadChest == null || SaveChest == null || replicate == null)
				{
					return "handoff_api_unavailable";
				}
				LoadChest.Invoke(val7, null);
				if (!OwnerAutomation.EligibleChest(val7, val5))
				{
					return "chest_changed";
				}
				Inventory inventory = val7.GetInventory();
				if (!HasInputs(val6, val4.GetZDO(), inventory, num4, num5))
				{
					return "no_needed_inputs";
				}
				SaveChest.Invoke(val7, null);
				ZPackage val9 = new ZPackage();
				inventory.Save(val9);
				byte[] array = val9.GetArray();
				byte[] byteArray = val5.GetZDO().GetByteArray(ZDOVars.s_items, (byte[])null);
				if (byteArray == null || array.Length != byteArray.Length)
				{
					return "save_not_verified";
				}
				for (int i = 0; i < byteArray.Length; i++)
				{
					if (byteArray[i] != array[i])
					{
						return "save_not_verified";
					}
				}
				if (!ReadyToGrant(val7, val5, val4, num2, playerId, num3, num))
				{
					return "state_changed";
				}
				replicate(num2, chestId);
				if (!ReadyToGrant(val7, val5, val4, num2, playerId, num3, num))
				{
					return "state_changed";
				}
				val5.GetZDO().SetOwner(num2);
				return (val5.GetZDO().GetOwner() == num2) ? "granted" : "grant_not_verified";
			}
			catch (Exception ex)
			{
				return "handoff_error:" + ex.GetType().Name;
			}
		}
	}
	internal static class StoreLease
	{
		internal const long DurationTicks = 100000000L;

		internal const long QuietTicks = 30000000L;

		internal static bool IsLive(long now, long deadline)
		{
			if (deadline > 0)
			{
				return now < deadline;
			}
			return false;
		}

		internal static bool CanDispatch(long now, long previousDeadline)
		{
			if (previousDeadline > 0)
			{
				return now >= previousDeadline + 30000000;
			}
			return true;
		}

		internal static bool Matches(int token, long owner, int reportedToken, long sender)
		{
			if (token > 0 && token == reportedToken)
			{
				return owner == sender;
			}
			return false;
		}
	}
	internal static class TransferSafety
	{
		internal static bool Commit(Action destination, Func<bool> destinationAccepted, Action source, Func<bool> sourceCommitted, Action restoreDestination, Action restoreSource)
		{
			bool flag = false;
			bool flag2 = false;
			try
			{
				flag = true;
				destination();
				if (!destinationAccepted())
				{
					throw new InvalidOperationException("Destination did not accept the transfer.");
				}
				flag2 = true;
				source();
				if (!sourceCommitted())
				{
					throw new InvalidOperationException("Source did not commit the transfer.");
				}
				return true;
			}
			catch (Exception ex)
			{
				Exception ex2 = null;
				if (flag2)
				{
					try
					{
						restoreSource();
					}
					catch (Exception ex3)
					{
						ex2 = ex3;
					}
				}
				if (flag)
				{
					try
					{
						restoreDestination();
					}
					catch (Exception ex4)
					{
						if (ex2 == null)
						{
							ex2 = ex4;
						}
					}
				}
				if (ex2 != null)
				{
					throw new InvalidOperationException("Transfer rollback failed; automation is paused for these objects.", new AggregateException(ex, ex2));
				}
				return false;
			}
		}
	}
}
namespace RustyHeathens.Backpacks
{
	internal sealed class BackpackDeathLocation
	{
		internal Vector3 DeathPoint;

		internal ZDOID GraveId = ZDOID.None;

		internal Vector3 GravePoint;
	}
	internal enum DeathLocationRead
	{
		Legacy,
		Valid,
		Invalid
	}
	internal static class BackpackDeathPlacement
	{
		internal const string AnchorKey = "RHSQOL_RustyBackpack_DeathAnchor";

		internal const float GraveSpacing = 1.25f;

		private const int WireMarker = 1380467249;

		internal static bool Finite(Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (Coordinate(point.x) && Coordinate(point.y))
			{
				return Coordinate(point.z);
			}
			return false;
		}

		private static bool Coordinate(float value)
		{
			if (!float.IsNaN(value) && !float.IsInfinity(value))
			{
				return Math.Abs(value) < 100000f;
			}
			return false;
		}

		internal static Vector3 Beside(Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			return point + Vector3.right * 1.25f;
		}

		internal static void Write(ZPackage report, ZDOID character, BackpackDeathLocation location)
		{
			//IL_000c: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			report.Write(1380467249);
			report.Write(character);
			report.Write(location.DeathPoint);
			report.Write(location.GraveId);
			report.Write(location.GravePoint);
		}

		internal static DeathLocationRead Read(ZPackage report, ZDOID character, out BackpackDeathLocation location)
		{
			//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_003d: 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_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_0055: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			location = null;
			if (report.GetPos() == report.Size())
			{
				return DeathLocationRead.Legacy;
			}
			try
			{
				if (report.ReadInt() != 1380467249 || report.ReadZDOID() != character)
				{
					return DeathLocationRead.Invalid;
				}
				BackpackDeathLocation backpackDeathLocation = new BackpackDeathLocation
				{
					DeathPoint = report.ReadVector3(),
					GraveId = report.ReadZDOID(),
					GravePoint = report.ReadVector3()
				};
				if (report.GetPos() != report.Size() || !Finite(backpackDeathLocation.DeathPoint) || !Finite(backpackDeathLocation.GravePoint))
				{
					return DeathLocationRead.Invalid;
				}
				if (!((ZDOID)(ref backpackDeathLocation.GraveId)).IsNone())
				{
					Vector3 val = backpackDeathLocation.GravePoint - backpackDeathLocation.DeathPoint;
					if (((Vector3)(ref val)).sqrMagnitude > 16f)
					{
						return DeathLocationRead.Invalid;
					}
				}
				location = backpackDeathLocation;
				return DeathLocationRead.Valid;
			}
			catch
			{
				return DeathLocationRead.Invalid;
			}
		}

		internal static bool IsInventoryGrave(ZDO grave, long playerId)
		{
			if (grave != null && grave.IsValid() && playerId != 0L && grave.GetPrefab() == StringExtensionMethods.GetStableHashCode("Player_tombstone") && grave.GetLong(ZDOVars.s_owner, 0L) == playerId && !grave.GetBool("RHSQOL_RustyBackpack_Grave", false))
			{
				return !grave.GetString(ZDOVars.s_ownerName, "").EndsWith(" - Rusty Backpack", StringComparison.Ordinal);
			}
			return false;
		}

		internal static Vector3 Resolve(BackpackDeathLocation location, Vector3 frozenDeathPoint, ZDO grave, long playerId, out ZDOID anchor)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0052: 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_005b: 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)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			anchor = ZDOID.None;
			if (location == null)
			{
				return frozenDeathPoint;
			}
			if (((ZDOID)(ref location.GraveId)).IsNone())
			{
				return location.DeathPoint;
			}
			if (grave != null)
			{
				if (grave.m_uid != location.GraveId || !IsInventoryGrave(grave, playerId) || !Finite(grave.GetPosition()))
				{
					return location.DeathPoint;
				}
				anchor = grave.m_uid;
				return Beside(grave.GetPosition());
			}
			anchor = location.GraveId;
			return Beside(location.GravePoint);
		}
	}
}
namespace RustyHeathens.QoL
{
	internal static class BackpackClient
	{
		internal const string RequestRpc = "RHSQOL_BackpackRequest_v2";

		internal const string AssignedRpc = "RHSQOL_BackpackAssigned_v2";

		internal const string DeathRpc = "RHSQOL_BackpackDeath_v2";

		private static readonly int Marker = StringExtensionMethods.GetStableHashCode("RHSQOL_RustyBackpack");

		private static readonly int PlayerKey = StringExtensionMethods.GetStableHashCode("RHSQOL_RustyBackpack_Player");

		private static readonly HashSet<Inventory> Weightless = new HashSet<Inventory>();

		internal static ZDOID AssignedId = ZDOID.None;

		internal static void Clear()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Weightless.Clear();
			AssignedId = ZDOID.None;
			BackpackDeathCapture.Clear();
		}

		internal static bool IsWeightless(Inventory inv)
		{
			if (inv != null)
			{
				return Weightless.Contains(inv);
			}
			return false;
		}

		internal static bool IsGrave(Container container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return false;
			}
			ZNetView component = ((Component)container).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return false;
			}
			ZDO zDO = component.GetZDO();
			if (!zDO.GetBool("RHSQOL_RustyBackpack_Grave", false))
			{
				return zDO.GetString(ZDOVars.s_ownerName, "").EndsWith(" - Rusty Backpack", StringComparison.Ordinal);
			}
			return true;
		}

		internal static void Register(Container container)
		{
			if ((Object)(object)container == (Object)null || container.GetInventory() == null)
			{
				return;
			}
			ZNetView component = ((Component)container).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return;
			}
			ZDO zDO = component.GetZDO();
			if (!zDO.GetBool(Marker, false) && !IsGrave(container))
			{
				return;
			}
			Weightless.Add(container.GetInventory());
			if (zDO.GetBool(Marker, false))
			{
				StandaloneInventory.SetRawHeight(height: container.m_height = Math.Max(container.GetInventory().GetHeight(), zDO.GetInt("Container.m_height", container.m_height)), inv: container.GetInventory());
				if ((Object)(object)Player.m_localPlayer != (Object)null && zDO.GetLong(PlayerKey, 0L) == Player.m_localPlayer.GetPlayerID())
				{
					StandaloneInventoryUI.RegisterRustyBackpack(container.GetInventory());
				}
			}
		}

		internal static Container OwnedBackpack()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (((ZDOID)(ref AssignedId)).IsNone() || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return null;
			}
			GameObject val = ZNetScene.instance.FindInstance(AssignedId);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			ZNetView component = val.GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner())
			{
				return null;
			}
			ZDO zDO = component.GetZDO();
			if (!zDO.GetBool(Marker, false) || zDO.GetLong(PlayerKey, 0L) != Player.m_localPlayer.GetPlayerID())
			{
				return null;
			}
			Container component2 = val.GetComponent<Container>();
			Register(component2);
			return component2;
		}

		private static byte[] Save(Inventory inv)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			inv.Save(val);
			return val.GetArray();
		}

		private static void Restore(Container container, byte[] bytes)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Load(bytes);
			container.GetInventory().Load(val);
			Persist(container);
		}

		private static void Persist(Container container)
		{
			ZNetView component = ((Component)container).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsOwner())
			{
				throw new InvalidOperationException("Backpack/grave ownership changed.");
			}
			AccessTools.Method(typeof(Container), "Save", Type.EmptyTypes, (Type[])null).Invoke(container, null);
			byte[] byteArray = component.GetZDO().GetByteArray(ZDOVars.s_items, (byte[])null);
			byte[] array = Save(container.GetInventory());
			if (byteArray == null || byteArray.Length != array.Length)
			{
				throw new InvalidOperationException("Recovery save failed.");
			}
			for (int i = 0; i < array.Length; i++)
			{
				if (byteArray[i] != array[i])
				{
					throw new InvalidOperationException("Recovery save failed.");
				}
			}
		}

		internal static bool Recover(Container grave)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)grave == (Object)null || !IsGrave(grave))
			{
				return false;
			}
			ZNetView component = ((Component)grave).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || component.GetZDO().GetLong(ZDOVars.s_owner, 0L) != localPlayer.GetPlayerID())
			{
				return false;
			}
			Container target = OwnedBackpack();
			if ((Object)(object)target == (Object)null || !component.IsOwner())
			{
				if ((Object)(object)Plugin.Instance != (Object)null)
				{
					Plugin.Instance.RequestBackpack(open: false, "wave");
				}
				((Character)localPlayer).Message((MessageType)2, "Open your Rusty Backpack with Wave, then use Take All on the backpack grave.", 0, (Sprite)null, false);
				return true;
			}
			Inventory src = grave.GetInventory();
			Inventory dst = target.GetInventory();
			List<ItemData> list = new List<ItemData>(src.GetAllItems());
			int num = 0;
			try
			{
				foreach (ItemData item in list)
				{
					if (item != null && dst.CanAddItem(item, item.m_stack))
					{
						byte[] beforeSrc = Save(src);
						byte[] beforeDst = Save(dst);
						int amount = item.m_stack;
						string name = item.m_shared.m_name;
						int sourceCount = src.CountItems(name, -1, true);
						int destCount = dst.CountItems(name, -1, true);
						if (TransferSafety.Commit(delegate
						{
							if (!dst.AddItem(item.Clone()))
							{
								throw new InvalidOperationException("Backpack is full.");
							}
							Persist(target);
						}, () => dst.CountItems(name, -1, true) == destCount + amount, delegate
						{
							if (!src.RemoveItem(item))
							{
								throw new InvalidOperationException("Grave changed.");
							}
							Persist(grave);
						}, () => src.CountItems(name, -1, true) == sourceCount - amount, delegate
						{
							Restore(target, beforeDst);
						}, delegate
						{
							Restore(grave, beforeSrc);
						}))
						{
							num++;
						}
					}
				}
			}
			catch (Exception ex)
			{
				if ((Object)(object)Plugin.Instance != (Object)null)
				{
					Plugin.Instance.LogWarning("[RHQOL Backpack] Recovery stopped: " + ex);
				}
				((Character)localPlayer).Message((MessageType)2, "Backpack recovery stopped. Check the log before retrying.", 0, (Sprite)null, false);
				return true;
			}
			((Character)localPlayer).Message((MessageType)2, num + " stack(s) returned to Rusty Backpack." + ((src.NrOfItems() > 0) ? " Remaining items stay in the grave until there is space." : ""), 0, (Sprite)null, false);
			if (src.NrOfItems() == 0)
			{
				TombStone component2 = ((Component)grave).GetComponent<TombStone>();
				if ((Object)(object)component2 != (Object)null)
				{
					try
					{
						AccessTools.Method(typeof(TombStone), "OnTakeAllSuccess", (Type[])null, (Type[])null).Invoke(component2, null);
					}
					catch
					{
					}
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	internal static class BackpackWeightRegistrationPatch
	{
		private static void Postfix(Container __instance)
		{
			BackpackClient.Register(__instance);
		}
	}
	[HarmonyPatch(typeof(Inventory), "GetTotalWeight")]
	internal static class WeightlessBackpackPatch
	{
		private static bool Prefix(Inventory __instance, ref float __result)
		{
			if (!BackpackClient.IsWeightless(__instance))
			{
				return true;
			}
			__result = 0f;
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "IsTeleportable")]
	internal static class BackpackTeleportCargoPatch
	{
		private static void Postfix(Inventory __instance, bool __0, ref bool __result)
		{
			Player localPlayer = Player.m_localPlayer;
			if (__result && !((Object)(object)localPlayer == (Object)null) && __instance == ((Humanoid)localPlayer).GetInventory())
			{
				Container val = BackpackClient.OwnedBackpack();
				if ((Object)(object)val != (Object)null && !val.GetInventory().IsTeleportable(__0))
				{
					__result = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(TombStone), "EasyFitInInventory")]
	internal static class BackpackGraveAutoLootPatch
	{
		private static bool Prefix(TombStone __instance, ref bool __result)
		{
			if (!BackpackClient.IsGrave(((Component)__instance).GetComponent<Container>()))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "OnTakeAll")]
	internal static class BackpackGraveTakeAllPatch
	{
		private static bool Prefix(Container ___m_currentContainer)
		{
			return !BackpackClient.Recover(___m_currentContainer);
		}
	}
	internal static class BackpackDeathCapture
	{
		internal sealed class Snapshot
		{
			internal ZDOID Backpack;

			internal ZDOID Character;

			internal long PlayerId;

			internal byte[] Items;

			internal BackpackDeathLocation Location;
		}

		private static Snapshot active;

		internal static void Clear()
		{
			active = null;
		}

		internal static Snapshot Begin(Player player)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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)
			active = null;
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || (Object)(object)Plugin.Instance == (Object)null)
			{
				return null;
			}
			ZNetView component = ((Component)player).GetComponent<ZNetView>();
			Container val = BackpackClient.OwnedBackpack();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner() || (Object)(object)val == (Object)null)
			{
				return null;
			}
			ZPackage val2 = new ZPackage();
			val.GetInventory().Save(val2);
			Vector3 centerPoint = ((Character)player).GetCenterPoint();
			active = new Snapshot
			{
				Backpack = BackpackClient.AssignedId,
				Character = component.GetZDO().m_uid,
				PlayerId = player.GetPlayerID(),
				Items = val2.GetArray(),
				Location = new BackpackDeathLocation
				{
					DeathPoint = centerPoint,
					GravePoint = centerPoint
				}
			};
			return active;
		}

		internal static void RecordGrave(TombStone grave, long owner)
		{
			//IL_004b: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0069: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			if (active == null || (Object)(object)grave == (Object)null || owner != active.PlayerId)
			{
				return;
			}
			ZNetView component = ((Component)grave).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !BackpackDeathPlacement.IsInventoryGrave(component.GetZDO(), owner))
			{
				return;
			}
			Vector3 position = ((Component)grave).transform.position;
			if (BackpackDeathPlacement.Finite(position))
			{
				Vector3 val = position - active.Location.DeathPoint;
				if (!(((Vector3)(ref val)).sqrMagnitude > 16f))
				{
					active.Location.GraveId = component.GetZDO().m_uid;
					active.Location.GravePoint = position;
				}
			}
		}

		internal static void Finish(Snapshot snapshot)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Clear();
			if (snapshot != null && !((Object)(object)Plugin.Instance == (Object)null))
			{
				ZPackage val = new ZPackage();
				val.Write(snapshot.Backpack);
				val.Write(snapshot.Items);
				BackpackDeathPlacement.Write(val, snapshot.Character, snapshot.Location);
				Plugin.Instance.SendToServer("RHSQOL_BackpackDeath_v2", val);
			}
		}
	}
	[HarmonyPatch(typeof(TombStone), "Setup")]
	internal static class BackpackDeathAnchorSetupPatch
	{
		private static void Postfix(TombStone __instance, long ownerUID)
		{
			BackpackDeathCapture.RecordGrave(__instance, ownerUID);
		}
	}
	[HarmonyPatch(typeof(Player), "OnDeath")]
	internal static class BackpackDeathFlushPatch
	{
		private static void Prefix(Player __instance, ref BackpackDeathCapture.Snapshot __state)
		{
			try
			{
				__state = BackpackDeathCapture.Begin(__instance);
			}
			catch (Exception ex)
			{
				if ((Object)(object)Plugin.Instance != (Object)null)
				{
					Plugin.Instance.LogWarning("[RHQOL Backpack] Death snapshot: " + ex.Message);
				}
			}
		}

		private static void Postfix(BackpackDeathCapture.Snapshot __state)
		{
			try
			{
				BackpackDeathCapture.Finish(__state);
			}
			catch (Exception ex)
			{
				if ((Object)(object)Plugin.Instance != (Object)null)
				{
					Plugin.Instance.LogWarning("[RHQOL Backpack] Death report: " + ex.Message);
				}
			}
		}

		private static void Finalizer()
		{
			BackpackDeathCapture.Clear();
		}
	}
	internal sealed class BackpackGraveAnchor : MonoBehaviour
	{
		private ZNetView view;

		private Rigidbody body;

		private bool pinned;

		private bool wasKinematic;

		private void Awake()
		{
			view = ((Component)this).GetComponent<ZNetView>();
			body = ((Component)this).GetComponent<Rigidbody>();
		}

		private void ReleaseBody()
		{
			if (pinned && (Object)(object)body != (Object)null)
			{
				body.isKinematic = wasKinematic;
			}
			pinned = false;
		}

		private void OnDisable()
		{
			ReleaseBody();
		}

		internal void Follow()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)view == (Object)null || !view.IsValid() || !view.IsOwner() || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				ReleaseBody();
				return;
			}
			ZDO zDO = view.GetZDO();
			if (!zDO.GetBool("RHSQOL_RustyBackpack_Grave", false))
			{
				ReleaseBody();
				return;
			}
			ZDOID zDOID = zDO.GetZDOID("RHSQOL_RustyBackpack_DeathAnchor");
			ZDO val = (((ZDOID)(ref zDOID)).IsNone() ? null : ZDOMan.instance.GetZDO(zDOID));
			if (!BackpackDeathPlacement.IsInventoryGrave(val, zDO.GetLong(ZDOVars.s_owner, 0L)))
			{
				ReleaseBody();
				return;
			}
			GameObject val2 = ZNetScene.instance.FindInstance(zDOID);
			Vector3 point = (((Object)(object)val2 == (Object)null) ? val.GetPosition() : val2.transform.position);
			if (!BackpackDeathPlacement.Finite(point))
			{
				ReleaseBody();
				return;
			}
			Vector3 val3 = BackpackDeathPlacement.Beside(point);
			if ((Object)(object)ZoneSystem.instance != (Object)null)
			{
				val3.y = Mathf.Max(val3.y, ZoneSystem.instance.GetGroundHeight(val3) + 0.5f);
			}
			if (!BackpackDeathPlacement.Finite(val3))
			{
				ReleaseBody();
				return;
			}
			Vector3 val4;
			if ((Object)(object)body != (Object)null)
			{
				if (!pinned)
				{
					wasKinematic = body.isKinematic;
					if (!wasKinematic)
					{
						body.linearVelocity = Vector3.zero;
						body.angularVelocity = Vector3.zero;
					}
					body.isKinematic = true;
					pinned = true;
				}
				val4 = body.position - val3;
				if (((Vector3)(ref val4)).sqrMagnitude > 0.0001f)
				{
					body.position = val3;
				}
			}
			val4 = ((Component)this).transform.position - val3;
			if (((Vector3)(ref val4)).sqrMagnitude > 0.0001f)
			{
				((Component)this).transform.position = val3;
			}
			val4 = zDO.GetPosition() - val3;
			if (!(((Vector3)(ref val4)).sqrMagnitude > 0.0001f))
			{
				val4 = zDO.GetVec3(ZDOVars.s_spawnPoint, val3 + Vector3.up) - val3;
				if (!(((Vector3)(ref val4)).sqrMagnitude > 0.0001f))
				{
					return;
				}
			}
			zDO.SetPosition(val3);
			zDO.Set(ZDOVars.s_spawnPoint, val3);
		}

		private void FixedUpdate()
		{
			Follow();
		}
	}
	[HarmonyPatch(typeof(TombStone), "Awake")]
	internal static class BackpackGraveAnchorAwakePatch
	{
		private static void Postfix(TombStone __instance)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid() && component.GetZDO().GetBool("RHSQOL_RustyBackpack_Grave", false))
			{
				ZDOID zDOID = component.GetZDO().GetZDOID("RHSQOL_RustyBackpack_DeathAnchor");
				if (!((ZDOID)(ref zDOID)).IsNone() && (Object)(object)((Component)__instance).GetComponent<BackpackGraveAnchor>() == (Object)null)
				{
					((Component)__instance).gameObject.AddComponent<BackpackGraveAnchor>();
				}
			}
		}
	}
	internal static class BackpackHostVisibility
	{
		private static readonly int MarkerKey = StringExtensionMethods.GetStableHashCode("RHSQOL_RustyBackpack");

		internal static void HideIfRustyBackpack(ZNetView view)
		{
			if ((Object)(object)view == (Object)null)
			{
				return;
			}
			ZNet instance = ZNet.instance;
			if ((Object)(object)instance != (Object)null && instance.IsServer())
			{
				return;
			}
			ZDO val = null;
			try
			{
				val = view.GetZDO();
			}
			catch
			{
			}
			if (val == null || !val.IsValid() || !val.GetBool(MarkerKey, false))
			{
				return;
			}
			GameObject gameObject = ((Component)view).gameObject;
			if ((Object)(object)gameObject == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren = gameObject.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					val2.enabled = false;
				}
			}
			Collider[] componentsInChildren2 = gameObject.GetComponentsInChildren<Collider>(true);
			foreach (Collider val3 in componentsInChildren2)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					val3.enabled = false;
				}
			}
			Light[] componentsInChildren3 = gameObject.GetComponentsInChildren<Light>(true);
			foreach (Light val4 in componentsInChildren3)
			{
				if ((Object)(object)val4 != (Object)null)
				{
					((Behaviour)val4).enabled = false;
				}
			}
			WearNTear component = gameObject.GetComponent<WearNTear>();
			if ((Object)(object)component != (Object)null)
			{
				((Behaviour)component).enabled = false;
			}
			Container component2 = gameObject.GetComponent<Container>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.m_name = "Rusty Backpack";
				component2.m_checkGuardStone = false;
				component2.m_autoDestroyEmpty = false;
			}
		}
	}
	[HarmonyPatch(typeof(ZNetView), "Awake")]
	internal static class RustyBackpackHostAwakePatch
	{
		private static void Postfix(ZNetView __instance)
		{
			try
			{
				BackpackHostVisibility.HideIfRustyBackpack(__instance);
			}
			catch (Exception ex)
			{
				Plugin instance = Plugin.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					instance.LogWarning("[RHQOL Backpack] Failed to hide dedicated backpack host on Awake: " + ex.Message);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ZNetView), "LoadFields")]
	internal static class RustyBackpackHostLoadFieldsPatch
	{
		private static void Postfix(ZNetView __instance)
		{
			try
			{
				BackpackHostVisibility.HideIfRustyBackpack(__instance);
			}
			catch (Exception ex)
			{
				Plugin instance = Plugin.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					instance.LogWarning("[RHQOL Backpack] Failed to hide dedicated backpack host after field load: " + ex.Message);
				}
			}
		}
	}
	internal static class CraftAuditClient
	{
		internal sealed class AuditState
		{
			internal Player Player;

			internal Inventory Inventory;

			internal string Station;

			internal Dictionary<string, int> Before;
		}

		private sealed class ItemSnapshot
		{
			internal string ItemKey;

			internal int Quality;

			internal int Count;
		}

		internal const string ReportRpc = "RHSQOL_CraftAudit_v1";

		private static readonly FieldInfo StationNameField = AccessTools.Field(typeof(CraftingStation), "m_name");

		private static AuditState pending;

		private static float pendingUntil;

		internal static void Clear()
		{
			pending = null;
			pendingUntil = 0f;
		}

		internal static void Tick()
		{
			AuditState auditState = pending;
			if (auditState == null)
			{
				return;
			}
			if (TryComplete(auditState))
			{
				pending = null;
				pendingUntil = 0f;
			}
			else if (Time.realtimeSinceStartup >= pendingUntil)
			{
				if ((Object)(object)Plugin.Instance != (Object)null)
				{
					Plugin.Instance.LogVerbose("CraftAudit verification expired without a positive inventory delta.");
				}
				pending = null;
				pendingUntil = 0f;
			}
		}

		internal static AuditState Begin(InventoryGui gui)
		{
			try
			{
				if ((Object)(object)gui == (Object)null || (Object)(object)Plugin.Instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer())
				{
					return null;
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					return null;
				}
				Inventory inventory = ((Humanoid)localPlayer).GetInventory();
				if (inventory == null)
				{
					return null;
				}
				AuditState auditState = new AuditState
				{
					Player = localPlayer,
					Inventory = inventory,
					Station = ResolveStation(localPlayer),
					Before = SnapshotInventory(inventory)
				};
				Plugin.Instance.LogCraftAuditClient("HOOK DoCrafting station=" + auditState.Station + " stacks=" + auditState.Before.Count + ".");
				return auditState;
			}
			catch (Exception ex)
			{
				if ((Object)(object)Plugin.Instance != (Object)null)
				{
					Plugin.Instance.LogCraftAuditClient("CAPTURE-ERROR " + ex.GetType().Name + ": " + ex.Message);
				}
				return null;
			}
		}

		internal static void Complete(AuditState state)
		{
			try
			{
				if (state != null && !((Object)(object)state.Player == (Object)null) && state.Inventory != null && !((Object)(object)Plugin.Instance == (Object)null) && state.Player == Player.m_localPlayer && !TryComplete(state))
				{
					pending = state;
					pendingUntil = Time.realtimeSinceStartup + 2f;
				}
			}
			catch (Exception ex)
			{
				if ((Object)(object)Plugin.Instance != (Object)null)
				{
					Plugin.Instance.LogCraftAuditClient("COMPLETE-ERROR " + ex.GetType().Name + ": " + ex.Message);
				}
			}
		}

		private static bool TryComplete(AuditState state)
		{
			try
			{
				if (state == null || (Object)(object)state.Player == (Object)null || state.Inventory == null || (Object)(object)Plugin.Instance == (Object)null)
				{
					return false;
				}
				if (state.Player != Player.m_localPlayer)
				{
					return false;
				}
				List<ItemSnapshot> list = SnapshotItems(state.Inventory);
				for (int i = 0; i < list.Count; i++)
				{
					ItemSnapshot itemSnapshot = list[i];
					int num = Read(state.Before, MakeKey(itemSnapshot.ItemKey, itemSnapshot.Quality));
					int num2 = itemSnapshot.Count - num;
					if (num2 <= 0)
					{
						continue;
					}
					bool flag = false;
					int qualityBefore = 0;
					int qualityAfter = 0;
					if (itemSnapshot.Quality > 1)
					{
						string key = MakeKey(itemSnapshot.ItemKey, itemSnapshot.Quality - 1);
						int num3 = Read(state.Before, key);
						int num4 = Count(list, itemSnapshot.ItemKey, itemSnapshot.Quality - 1);
						if (num3 > num4)
						{
							flag = true;
							qualityBefore = itemSnapshot.Quality - 1;
							qualityAfter = itemSnapshot.Quality;
						}
					}
					if (flag)
					{
						Send("UPGRADE", itemSnapshot.ItemKey, Localize(itemSnapshot.ItemKey), 1, qualityBefore, qualityAfter, state.Station);
					}
					else
					{
						Send("CRAFT", itemSnapshot.ItemKey, Localize(itemSnapshot.ItemKey), num2, 0, 0, state.Station);
					}
					return true;
				}
				return false;
			}
			catch (Exception ex)
			{
				if ((Object)(object)Plugin.Instance != (Object)null)
				{
					Plugin.Instance.LogCraftAuditClient("VERIFY-ERROR " + ex.GetType().Name + ": " + ex.Message);
				}
				return false;
			}
		}

		private static Dictionary<string, int> SnapshotInventory(Inventory inventory)
		{
			Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal);
			List<ItemSnapshot> list = SnapshotItems(inventory);
			for (int i = 0; i < list.Count; i++)
			{
				dictionary[MakeKey(list[i].ItemKey, list[i].Quality)] = list[i].Count;
			}
			return dictionary;
		}

		private static List<ItemSnapshot> SnapshotItems(Inventory inventory)
		{
			Dictionary<string, ItemSnapshot> dictionary = new Dictionary<string, ItemSnapshot>(StringComparer.Ordinal);
			if (inventory == null)
			{
				return new List<ItemSnapshot>();
			}
			List<ItemData> allItems = inventory.GetAllItems();
			if (allItems == null)
			{
				return new List<ItemSnapshot>();
			}
			for (int i = 0; i < allItems.Count; i++)
			{
				ItemData val = allItems[i];
				if (val != null && val.m_shared != null && !string.IsNullOrWhiteSpace(val.m_shared.m_name) && val.m_stack > 0)
				{
					string key = MakeKey(val.m_shared.m_name, val.m_quality);
					if (!dictionary.TryGetValue(key, out var value))
					{
						value = new ItemSnapshot
						{
							ItemKey = val.m_shared.m_name,
							Quality = val.m_quality,
							Count = 0
						};
						dictionary.Add(key, value);
					}
					value.Count += val.m_stack;
				}
			}
			return new List<ItemSnapshot>(dictionary.Values);
		}

		private static int Count(List<ItemSnapshot> items, string itemKey, int quality)
		{
			if (items == null || string.IsNullOrEmpty(itemKey))
			{
				return 0;
			}
			for (int i = 0; i < items.Count; i++)
			{
				ItemSnapshot itemSnapshot = items[i];
				if (itemSnapshot != null && itemSnapshot.Quality == quality && string.Equals(itemSnapshot.ItemKey, itemKey, StringComparison.Ordinal))
				{
					return itemSnapshot.Count;
				}
			}
			return 0;
		}

		private static string MakeKey(string itemKey, int quality)
		{
			return (itemKey ?? string.Empty) + "\u001f" + quality;
		}

		private static int Read(Dictionary<string, int> map, string key)
		{
			if (map == null || key == null)
			{
				return 0;
			}
			if (!map.TryGetValue(key, out var value))
			{
				return 0;
			}
			return value;
		}

		private static void Send(string action, string itemKey, string itemDisplay, int amount, int qualityBefore, int qualityAfter, string station)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			if (!((Object)(object)Plugin.Instance == (Object)null) && !((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer())
			{
				ZPackage val = new ZPackage();
				val.Write(1);
				val.Write(action ?? string.Empty);
				val.Write(itemKey ?? string.Empty);
				val.Write(itemDisplay ?? string.Empty);
				val.Write(amount);
				val.Write(qualityBefore);
				val.Write(qualityAfter);
				val.Write(station ?? string.Empty);
				Plugin.Instance.SendToServer("RHSQOL_CraftAudit_v1", val);
				Plugin.Instance.LogCraftAuditClient("SENT " + action + " item=" + (itemDisplay ?? itemKey) + " qty=" + amount + " station=" + (station ?? "Unknown") + ".");
			}
		}

		private static string ResolveStation(Player player)
		{
			try
			{
				CraftingStation station = ChestCrafting.GetStation(player);
				if ((Object)(object)station == (Object)null)
				{
					return "Handcraft";
				}
				string text = ((StationNameField == null) ? null : (StationNameField.GetValue(station) as string));
				if (string.IsNullOrWhiteSpace(text) && (Object)(object)((Component)station).gameObject != (Object)null)
				{
					text = ((Object)((Component)station).gameObject).name;
				}
				return Localize(text);
			}
			catch
			{
				return "Unknown";
			}
		}

		private static string Localize(string text)
		{
			if (string.IsNullOrWhiteSpace(text))
			{
				return "Unknown";
			}
			try
			{
				if (Localization.instance != null)
				{
					string text2 = Localization.instance.Localize(text);
					if (!string.IsNullOrWhiteSpace(text2))
					{
						return text2;
					}
				}
			}
			catch
			{
			}
			return text;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
	internal static class CraftAuditDoCraftingPatch
	{
		private static void Prefix(InventoryGui __instance, ref CraftAuditClient.AuditState __state)
		{
			__state = CraftAuditClient.Begin(__instance);
		}

		private static void Postfix(CraftAuditClient.AuditState __state)
		{
			CraftAuditClient.Complete(__state);
		}
	}
	[HarmonyPatch(typeof(Player), "Update")]
	internal static class FoodHotkeySitSuppressionPatch
	{
		private static void Prefix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)null || __instance != Player.m_localPlayer || (!Input.GetKey((KeyCode)308) && !Input.GetKey((KeyCode)307)) || !Input.GetKeyDown((KeyCode)120))
			{
				return;
			}
			try
			{
				ZInput.ResetButtonStatus("Sit");
				ZInput.ResetButtonStatus("JoySit");
			}
			catch
			{
			}
		}
	}
	internal static class GearGraveService
	{
		internal const string MarkerName = "GEAR";

		private static readonly Color GearRed = new Color(1f, 0.05f, 0.05f, 1f);

		private static readonly HashSet<TombStone> Loaded = new HashSet<TombStone>();

		private static readonly Dictionary<ZDOID, PinData> Markers = new Dictionary<ZDOID, PinData>();

		private static readonly HashSet<ZDOID> Recovered = new HashSet<ZDOID>();

		private static readonly MethodInfo LoadContainer = AccessTools.Method(typeof(Container), "CheckForChanges", Type.EmptyTypes, (Type[])null);

		private static readonly FieldInfo SceneInstances = AccessTools.Field(typeof(ZNetScene), "m_instances");

		private static float nextTick;

		private static float nextDiscovery;

		private static Vector3 pendingDeathPosition;

		private static float pendingDeathUntil;

		internal static void Clear()
		{
			Loaded.Clear();
			Markers.Clear();
			Recovered.Clear();
			nextTick = (nextDiscovery = (pendingDeathUntil = 0f));
		}

		internal static void Observe(TombStone grave)
		{
			if ((Object)(object)grave != (Object)null)
			{
				Loaded.Add(grave);
			}
		}

		internal unsafe static void RegisterDeath(Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			pendingDeathPosition = position;
			pendingDeathUntil = Time.realtimeSinceStartup + 15f;
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				Plugin instance = Plugin.Instance;
				Vector3 val = position;
				instance.LogGearMarker("DEATH with gear at " + ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString() + "; waiting for the ordinary player grave.");
			}
		}

		internal static IEnumerator RegisterAfterSetup(TombStone grave, long ownerUid)
		{
			Observe(grave);
			for (int attempt = 0; attempt < 30; attempt++)
			{
				if (!((Object)(object)grave != (Object)null))
				{
					break;
				}
				CheckGrave(grave);
				ZNetView component = ((Component)grave).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid() && Markers.ContainsKey(component.GetZDO().m_uid))
				{
					break;
				}
				yield return (object)new WaitForSeconds(0.1f);
			}
		}

		internal unsafe static void Tick()
		{
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Plugin.Instance == (Object)null || Plugin.Instance.Effective == null || !Plugin.Instance.Effective.GearGraveMarker || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Minimap.instance == (Object)null || Time.realtimeSinceStartup < nextTick)
			{
				return;
			}
			nextTick = Time.realtimeSinceStartup + 0.5f;
			if (Time.realtimeSinceStartup >= nextDiscovery)
			{
				nextDiscovery = Time.realtimeSinceStartup + 5f;
				IDictionary dictionary = (((Object)(object)ZNetScene.instance == (Object)null || SceneInstances == null) ? null : (SceneInstances.GetValue(ZNetScene.instance) as IDictionary));
				if (dictionary != null)
				{
					foreach (object item in new ArrayList(dictionary.Values))
					{
						ZNetView val = (ZNetView)((item is ZNetView) ? item : null);
						if (!((Object)(object)val == (Object)null) && val.IsValid() && val.GetZDO().GetPrefab() == StringExtensionMethods.GetStableHashCode("tombstone"))
						{
							Observe(((Component)val).GetComponent<TombStone>());
						}
					}
				}
			}
			foreach (TombStone item2 in new List<TombStone>(Loaded))
			{
				if ((Object)(object)item2 == (Object)null)
				{
					Loaded.Remove(item2);
				}
				else
				{
					CheckGrave(item2);
				}
			}
			if (pendingDeathUntil > 0f && Time.realtimeSinceStartup >= pendingDeathUntil)
			{
				pendingDeathUntil = 0f;
				Plugin instance = Plugin.Instance;
				Vector3 val2 = pendingDeathPosition;
				instance.LogGearMarker("WAIT: no loaded ordinary gear grave confirmed at " + ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString());
			}
		}

		internal unsafe static void CheckGrave(TombStone grave)
		{
			//IL_009d: 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_00a9: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			SyncedSettings syncedSettings = (((Object)(object)Plugin.Instance == (Object)null) ? null : Plugin.Instance.Effective);
			if ((Object)(object)grave == (Object)null || syncedSettings == null || !syncedSettings.GearGraveMarker || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Minimap.instance == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)grave).GetComponent<ZNetView>();
			Container container = GetContainer(grave);
			if ((Object)(object)component == (Object)null || !component.IsValid() || (Object)(object)container == (Object)null || BackpackClient.IsGrave(container))
			{
				return;
			}
			ZDO zDO = component.GetZDO();
			if (zDO.GetLong(ZDOVars.s_owner, 0L) != Player.m_localPlayer.GetPlayerID())
			{
				return;
			}
			ZDOID uid = zDO.m_uid;
			if (Recovered.Contains(uid))
			{
				return;
			}
			if (LoadContainer != null && !container.IsInUse())
			{
				LoadContainer.Invoke(container, null);
			}
			Inventory inventory = container.GetInventory();
			if (inventory == null)
			{
				return;
			}
			PinData value;
			bool flag = Markers.TryGetValue(uid, out value);
			string text = (((Object)(object)ZNet.instance == (Object)null) ? 0 : ZNet.instance.GetWorldUID()).ToString();
			ZDOID val = uid;
			string key = "rhqol_geargrave_v2_" + text + "_" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString();
			string value2;
			bool flag2 = Player.m_localPlayer.m_customData.TryGetValue(key, out value2);
			if (!flag && flag2)
			{
				value = FindUnboundPin(TryPosition(value2, out var position) ? position : ((Component)grave).transform.position);
				if (value != null)
				{
					Markers[uid] = value;
					flag = true;
				}
			}
			if (ContainsRealGear(inventory))
			{
				if (!flag)
				{
					value = FindUnboundPin(((Component)grave).transform.position);
					if (value == null)
					{
						value = Minimap.instance.AddPin(((Component)grave).transform.position, (PinType)4, "GEAR", true, false, 0L, default(PlatformUserID));
					}
					Markers[uid] = value;
					Plugin instance = Plugin.Instance;
					val = uid;
					instance.LogGearMarker("MARKED own gear grave=" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString() + " items=" + inventory.NrOfItems());
				}
				if (!flag2)
				{
					Player.m_localPlayer.m_customData[key] = PositionText(value.m_pos);
				}
				value.m_pos = ((Component)grave).transform.position;
				Tint(value);
				if (Time.realtimeSinceStartup < pendingDeathUntil)
				{
					Vector3 val2 = pendingDeathPosition - value.m_pos;
					if (((Vector3)(ref val2)).sqrMagnitude < 36f)
					{
						pendingDeathUntil = 0f;
					}
				}
			}
			else if (GearMarkerRules.ShouldClear(ownGrave: true, backpackGrave: false, flag || flag2, VerifiedEmpty(inventory, zDO)))
			{
				if (value != null)
				{
					Minimap.instance.RemovePin(value);
				}
				Markers.Remove(uid);
				Recovered.Add(uid);
				Player.m_localPlayer.m_customData.Remove(key);
				Plugin instance2 = Plugin.Instance;
				val = uid;
				instance2.LogGearMarker("CLEARED recovered gear grave=" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString());
			}
		}

		private static string PositionText(Vector3 p)
		{
			return p.x.ToString("R", CultureInfo.InvariantCulture) + "," + p.y.ToString("R", CultureInfo.InvariantCulture) + "," + p.z.ToString("R", CultureInfo.InvariantCulture);
		}

		private static bool TryPosition(string value, out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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)
			position = default(Vector3);
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			string[] array = value.Split(',');
			if (array.Length != 3 || !float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
			{
				return false;
			}
			position = new Vector3(result, result2, result3);
			return true;
		}

		private static bool VerifiedEmpty(Inventory inv, ZDO zdo)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			if (inv.NrOfItems() != 0)
			{
				return false;
			}
			byte[] byteArray = zdo.GetByteArray(ZDOVars.s_items, (byte[])null);
			if (byteArray == null)
			{
				return false;
			}
			ZPackage val = new ZPackage();
			inv.Save(val);
			byte[] array = val.GetArray();
			if (byteArray.Length != array.Length)
			{
				return false;
			}
			for (int i = 0; i < byteArray.Length; i++)
			{
				if (byteArray[i] != array[i])
				{
					return false;
				}
			}
			return true;
		}

		private static PinData FindUnboundPin(Vector3 position)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			/