Decompiled source of DropCrate v1.0.0

DropCrate.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Splatform;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("DropCrate")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+62397caa6e8b1cd12b5aec72e5ca03a7ae90940f")]
[assembly: AssemblyProduct("DropCrate")]
[assembly: AssemblyTitle("DropCrate")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DropCrate
{
	public static class DropCrateConfig
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<float> ScanIntervalSeconds;

		public static ConfigEntry<float> ScanRadius;

		public static ConfigEntry<int> ClusterItemThreshold;

		public static ConfigEntry<float> ClusterRadius;

		public static ConfigEntry<float> PlayerDropGracePeriodSeconds;

		public static ConfigEntry<bool> RespectWards;

		public static ConfigEntry<int> CrateWidth;

		public static ConfigEntry<int> CrateHeight;

		public static ConfigEntry<bool> SweepIntoExistingCrates;

		public static ConfigEntry<bool> AutoDestroyWhenEmpty;

		public static ConfigEntry<bool> EnableBeaconLight;

		public static ConfigEntry<float> CrateScale;

		public static ConfigEntry<bool> ShowMapPin;

		public static ConfigEntry<bool> ShowItemCountInPin;

		public static ConfigEntry<bool> PlaySoundOnSweep;

		public static ConfigEntry<bool> PlayVfxOnSweep;

		public static void Init(ConfigFile config)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Expected O, but got Unknown
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Expected O, but got Unknown
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Expected O, but got Unknown
			Enabled = config.Bind<bool>("1 - General", "Enabled", true, "Enable or disable DropCrate ground item consolidation to prevent FPS lag.");
			ScanIntervalSeconds = config.Bind<float>("1 - General", "ScanIntervalSeconds", 3f, new ConfigDescription("How frequently (in seconds) the area around the player is scanned for ground items.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			ScanRadius = config.Bind<float>("1 - General", "ScanRadius", 50f, new ConfigDescription("Maximum distance (in meters) around the local player to look for loose items.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 120f), Array.Empty<object>()));
			ClusterItemThreshold = config.Bind<int>("1 - General", "ClusterItemThreshold", 10, new ConfigDescription("Minimum number of loose items in a cluster required to condense them into a temporary Drop Crate.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 100), Array.Empty<object>()));
			ClusterRadius = config.Bind<float>("1 - General", "ClusterRadius", 10f, new ConfigDescription("Maximum distance (in meters) between items to be grouped into the same cluster.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 30f), Array.Empty<object>()));
			PlayerDropGracePeriodSeconds = config.Bind<float>("1 - General", "PlayerDropGracePeriodSeconds", 6f, new ConfigDescription("Grace period (in seconds) for items manually dropped by players before they can be swept. Prevents accidental scooping during player trades.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>()));
			RespectWards = config.Bind<bool>("1 - General", "RespectWards", false, "If true, items inside active ward protection fields will NOT be swept into crates.");
			CrateWidth = config.Bind<int>("2 - Crate Settings", "CrateWidth", 8, new ConfigDescription("Container inventory width (columns).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 10), Array.Empty<object>()));
			CrateHeight = config.Bind<int>("2 - Crate Settings", "CrateHeight", 6, new ConfigDescription("Container inventory height (rows). Default 6 (8x6 = 48 slots).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 10), Array.Empty<object>()));
			SweepIntoExistingCrates = config.Bind<bool>("2 - Crate Settings", "SweepIntoExistingCrates", true, "If new loose items drop near an existing un-filled Drop Crate, automatically pull them into it.");
			AutoDestroyWhenEmpty = config.Bind<bool>("2 - Crate Settings", "AutoDestroyWhenEmpty", true, "Automatically destroy the crate and remove its map pin once completely emptied.");
			EnableBeaconLight = config.Bind<bool>("2 - Crate Settings", "EnableBeaconLight", true, "Add a warm glowing beacon point-light to the crate so it stands out in grass and darkness.");
			CrateScale = config.Bind<float>("2 - Crate Settings", "CrateScale", 1f, new ConfigDescription("Visual scale factor for the recovery crate model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2.5f), Array.Empty<object>()));
			ShowMapPin = config.Bind<bool>("3 - Map Pin", "ShowMapPin", true, "Show a map and mini-map pin for every active Drop Crate.");
			ShowItemCountInPin = config.Bind<bool>("3 - Map Pin", "ShowItemCountInPin", true, "Show item count in the map pin hover text (e.g. 'Drop Crate (24 items)').");
			PlaySoundOnSweep = config.Bind<bool>("4 - Sound & VFX", "PlaySoundOnSweep", true, "Play a chest / salvage sound when loose items are swept into a crate.");
			PlayVfxOnSweep = config.Bind<bool>("4 - Sound & VFX", "PlayVfxOnSweep", true, "Spawn a subtle poof / particle effect at the crate when items are swept.");
		}
	}
	public class DropCrateController : MonoBehaviour
	{
		public static readonly List<DropCrateController> s_activeCrates = new List<DropCrateController>();

		private static readonly FieldRef<Inventory, int> s_invWidth = AccessTools.FieldRefAccess<Inventory, int>("m_width");

		private static readonly FieldRef<Inventory, int> s_invHeight = AccessTools.FieldRefAccess<Inventory, int>("m_height");

		private Container m_container;

		private ZNetView m_nview;

		private PinData m_pin;

		private float m_lastPinUpdate;

		private bool m_emptied;

		private bool m_hasHadItems;

		public Container Container => m_container;

		public ZNetView NetView => m_nview;

		public static void PresizeContainer(Container c)
		{
			if (!((Object)(object)c == (Object)null))
			{
				c.m_name = "Drop Crate";
				c.m_width = DropCrateConfig.CrateWidth.Value;
				c.m_height = DropCrateConfig.CrateHeight.Value;
				c.m_checkGuardStone = false;
				c.m_autoDestroyEmpty = false;
				Inventory inventory = c.GetInventory();
				if (inventory != null)
				{
					s_invWidth.Invoke(inventory) = c.m_width;
					s_invHeight.Invoke(inventory) = c.m_height;
				}
			}
		}

		private void Awake()
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_container = ((Component)this).GetComponent<Container>();
			if ((Object)(object)m_container != (Object)null)
			{
				PresizeContainer(m_container);
			}
			WearNTear component = ((Component)this).GetComponent<WearNTear>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_noSupportWear = false;
				component.m_noRoofWear = false;
				component.m_burnable = false;
				component.m_ashDamageImmune = true;
				component.m_health = 100000f;
			}
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
			GameObject val = DropCrateGlb.LoadGlb("recovery_crate.glb");
			if ((Object)(object)val != (Object)null)
			{
				((Object)val).name = "DropCrate_Visual";
				val.transform.SetParent(((Component)this).transform, false);
				float num = Mathf.Max(0.5f, DropCrateConfig.CrateScale.Value);
				val.transform.localScale = Vector3.one * num;
				val.transform.localPosition = Vector3.zero;
				val.transform.localRotation = Quaternion.identity;
				BoxCollider obj = ((Component)this).GetComponent<BoxCollider>() ?? ((Component)this).gameObject.AddComponent<BoxCollider>();
				((Collider)obj).enabled = true;
				obj.center = new Vector3(0f, 0.4f * num, 0f);
				obj.size = new Vector3(1f * num, 0.8f * num, 0.8f * num);
			}
			if (DropCrateConfig.EnableBeaconLight.Value)
			{
				GameObject val2 = new GameObject("CrateBeaconLight");
				val2.transform.SetParent(((Component)this).transform, false);
				val2.transform.localPosition = new Vector3(0f, 1.25f, 0f);
				Light obj2 = val2.AddComponent<Light>();
				obj2.type = (LightType)2;
				obj2.color = new Color(1f, 0.78f, 0.25f);
				obj2.range = 8f;
				obj2.intensity = 1.6f;
			}
			s_activeCrates.Add(this);
		}

		private void Start()
		{
			UpdatePinAndName();
		}

		private void Update()
		{
			if (!m_emptied)
			{
				if (GetTotalItemCount() > 0)
				{
					m_hasHadItems = true;
				}
				else if (m_hasHadItems && DropCrateConfig.AutoDestroyWhenEmpty.Value && (Object)(object)m_container != (Object)null)
				{
					m_emptied = true;
					DestroyCrate();
					return;
				}
				if (Time.time - m_lastPinUpdate > 2f)
				{
					m_lastPinUpdate = Time.time;
					UpdatePinAndName();
				}
			}
		}

		public int GetTotalItemCount()
		{
			if ((Object)(object)m_container == (Object)null)
			{
				return 0;
			}
			Inventory inventory = m_container.GetInventory();
			if (inventory == null)
			{
				return 0;
			}
			int num = 0;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem != null && allItem.m_stack > 0)
				{
					num += allItem.m_stack;
				}
			}
			return num;
		}

		public void UpdatePinAndName()
		{
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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)
			if ((Object)(object)m_container == (Object)null)
			{
				return;
			}
			int totalItemCount = GetTotalItemCount();
			if (m_container.GetInventory() != null)
			{
				m_container.GetInventory().NrOfItems();
			}
			if (totalItemCount > 0)
			{
				m_container.m_name = $"Drop Crate ({totalItemCount} items)";
			}
			else
			{
				m_container.m_name = "Drop Crate";
			}
			if (!DropCrateConfig.ShowMapPin.Value || (Object)(object)Minimap.instance == (Object)null)
			{
				RemovePin();
				return;
			}
			string text = ((DropCrateConfig.ShowItemCountInPin.Value && totalItemCount > 0) ? $"Drop Crate ({totalItemCount} items)" : "Drop Crate");
			if (m_pin == null)
			{
				m_pin = Minimap.instance.AddPin(((Component)this).transform.position, DropCratePlugin.DropCratePinType, text, false, false, 0L, default(PlatformUserID));
				if (m_pin != null)
				{
					m_pin.m_doubleSize = false;
				}
			}
			else
			{
				m_pin.m_name = text;
				m_pin.m_pos = ((Component)this).transform.position;
			}
		}

		private void RemovePin()
		{
			if (m_pin != null && (Object)(object)Minimap.instance != (Object)null)
			{
				Minimap.instance.RemovePin(m_pin);
				m_pin = null;
			}
		}

		public void DestroyCrate()
		{
			RemovePin();
			if ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && (Object)(object)ZNetScene.instance != (Object)null)
			{
				if (!m_nview.IsOwner())
				{
					m_nview.ClaimOwnership();
				}
				ZNetScene.instance.Destroy(((Component)this).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void OnDestroy()
		{
			s_activeCrates.Remove(this);
			RemovePin();
		}
	}
	[HarmonyPatch(typeof(Container), "Awake")]
	internal static class DropCrateContainerAwakePatch
	{
		private static void Prefix(Container __instance)
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<DropCrateController>() != (Object)null)
			{
				DropCrateController.PresizeContainer(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(WearNTear))]
	internal static class DropCrateWearNTearPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("UpdateWear")]
		private static bool PrefixUpdateWear(WearNTear __instance)
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<DropCrateController>() != (Object)null)
			{
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch("HaveSupport")]
		private static bool PrefixHaveSupport(WearNTear __instance, ref bool __result)
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<DropCrateController>() != (Object)null)
			{
				__result = true;
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch("GetSupport")]
		private static bool PrefixGetSupport(WearNTear __instance, ref float __result)
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<DropCrateController>() != (Object)null)
			{
				__result = 1500f;
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch("Destroy")]
		private static bool PrefixDestroy(WearNTear __instance)
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<DropCrateController>() != (Object)null)
			{
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch("ApplyDamage")]
		private static bool PrefixApplyDamage(WearNTear __instance)
		{
			if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<DropCrateController>() != (Object)null)
			{
				return false;
			}
			return true;
		}
	}
	public static class DropCrateGlb
	{
		[Serializable]
		private class GLTFRoot
		{
			public GLTFScene[] scenes;

			public GLTFNode[] nodes;

			public GLTFMesh[] meshes;

			public GLTFMaterial[] materials;

			public GLTFAccessor[] accessors;

			public GLTFBufferView[] bufferViews;

			public GLTFTexture[] textures;

			public GLTFImage[] images;
		}

		[Serializable]
		private class GLTFMesh
		{
			public string name;

			public GLTFPrimitive[] primitives;
		}

		[Serializable]
		private class GLTFPrimitive
		{
			public GLTFAttributes attributes;

			public int indices = -1;

			public int material = -1;
		}

		[Serializable]
		private class GLTFAttributes
		{
			public int POSITION = -1;

			public int NORMAL = -1;

			public int TEXCOORD_0 = -1;
		}

		[Serializable]
		private class GLTFNode
		{
			public string name;

			public int mesh = -1;

			public float[] translation;

			public float[] rotation;

			public float[] scale;

			public int[] children;
		}

		[Serializable]
		private class GLTFMaterial
		{
			public string name;

			public GLTFPBR pbrMetallicRoughness;
		}

		[Serializable]
		private class GLTFPBR
		{
			public float[] baseColorFactor;

			public float? metallicFactor;

			public float? roughnessFactor;

			public GLTFTextureInfo baseColorTexture;
		}

		[Serializable]
		private class GLTFTextureInfo
		{
			public int index = -1;
		}

		[Serializable]
		private class GLTFImage
		{
			public int bufferView = -1;

			public string name;
		}

		[Serializable]
		private class GLTFTexture
		{
			public int source = -1;
		}

		[Serializable]
		private class GLTFAccessor
		{
			public int bufferView;

			public int byteOffset;

			public int componentType;

			public int count;

			public string type;
		}

		[Serializable]
		private class GLTFBufferView
		{
			public int byteOffset;

			public int byteLength;

			public int byteStride;
		}

		[Serializable]
		private class GLTFScene
		{
			public int[] nodes;
		}

		private static readonly Dictionary<string, GameObject> s_cachedPrefabs = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase);

		public static GameObject LoadGlb(string fileNameOrPath, Material sourceMaterialTemplate = null)
		{
			string text = (File.Exists(fileNameOrPath) ? fileNameOrPath : DropCratePlugin.PluginFile(fileNameOrPath));
			if (string.IsNullOrEmpty(text) || !File.Exists(text))
			{
				DropCratePlugin.Log.LogError((object)("DropCrateGlb: Model file not found: " + fileNameOrPath));
				return null;
			}
			if (s_cachedPrefabs.TryGetValue(text, out var value) && (Object)(object)value != (Object)null)
			{
				GameObject obj = Object.Instantiate<GameObject>(value);
				obj.SetActive(true);
				return obj;
			}
			try
			{
				byte[] array = File.ReadAllBytes(text);
				if (array.Length < 20 || BitConverter.ToUInt32(array, 0) != 1179937895)
				{
					DropCratePlugin.Log.LogError((object)("DropCrateGlb: File is not a valid GLB: " + text));
					return null;
				}
				int num = 12;
				string text2 = null;
				byte[] array2 = null;
				while (num < array.Length && num + 8 <= array.Length)
				{
					uint num2 = BitConverter.ToUInt32(array, num);
					uint num3 = BitConverter.ToUInt32(array, num + 4);
					num += 8;
					switch (num3)
					{
					case 1313821514u:
						text2 = Encoding.UTF8.GetString(array, num, (int)num2);
						break;
					case 5130562u:
						array2 = new byte[num2];
						Buffer.BlockCopy(array, num, array2, 0, (int)num2);
						break;
					}
					num += (int)num2;
					num = (num + 3) & -4;
				}
				if (string.IsNullOrEmpty(text2) || array2 == null)
				{
					return null;
				}
				Shader shader = (((Object)(object)sourceMaterialTemplate != (Object)null) ? sourceMaterialTemplate.shader : FindValidShader());
				GameObject val = ParseGLTF(text2, array2, shader, Path.GetFileNameWithoutExtension(text));
				if ((Object)(object)val != (Object)null)
				{
					val.SetActive(false);
					Object.DontDestroyOnLoad((Object)(object)val);
					s_cachedPrefabs[text] = val;
					GameObject obj2 = Object.Instantiate<GameObject>(val);
					obj2.SetActive(true);
					return obj2;
				}
			}
			catch (Exception ex)
			{
				DropCratePlugin.Log.LogError((object)("DropCrateGlb: Exception loading GLB " + text + ": " + ex));
			}
			return null;
		}

		public static Shader FindValidShader()
		{
			Shader val = Shader.Find("Custom/Piece") ?? Shader.Find("Custom/StaticObject") ?? Shader.Find("Custom/Creature") ?? Shader.Find("Standard");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			try
			{
				Shader[] array = Resources.FindObjectsOfTypeAll<Shader>();
				foreach (Shader val2 in array)
				{
					if (((Object)val2).name == "Custom/Piece" || ((Object)val2).name == "Custom/StaticObject" || ((Object)val2).name == "Standard")
					{
						return val2;
					}
				}
			}
			catch
			{
			}
			return Shader.Find("Diffuse") ?? Shader.Find("Unlit/Texture");
		}

		private static GameObject ParseGLTF(string json, byte[] binData, Shader shader, string rootName)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			//IL_059f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a5: Expected O, but got Unknown
			//IL_05e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_042c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_0633: Unknown result type (might be due to invalid IL or missing references)
			//IL_04de: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_0677: Unknown result type (might be due to invalid IL or missing references)
			//IL_0459: Unknown result type (might be due to invalid IL or missing references)
			//IL_045f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0464: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_0476: 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_048e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			//IL_0492: Unknown result type (might be due to invalid IL or missing references)
			//IL_049c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0748: Unknown result type (might be due to invalid IL or missing references)
			//IL_0756: Unknown result type (might be due to invalid IL or missing references)
			//IL_075b: 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_04bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0400: Expected O, but got Unknown
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(rootName);
			GLTFRoot gLTFRoot = JsonConvert.DeserializeObject<GLTFRoot>(json);
			if (gLTFRoot == null)
			{
				return null;
			}
			GLTFBufferView[] bufferViews = gLTFRoot.bufferViews ?? new GLTFBufferView[0];
			GLTFAccessor[] array = gLTFRoot.accessors ?? new GLTFAccessor[0];
			GLTFMesh[] array2 = gLTFRoot.meshes ?? new GLTFMesh[0];
			GLTFMaterial[] array3 = gLTFRoot.materials ?? new GLTFMaterial[0];
			GLTFNode[] array4 = gLTFRoot.nodes ?? new GLTFNode[0];
			GLTFTexture[] array5 = gLTFRoot.textures ?? new GLTFTexture[0];
			GLTFImage[] images = gLTFRoot.images ?? new GLTFImage[0];
			Dictionary<int, Texture2D> texCache = new Dictionary<int, Texture2D>();
			Func<int, Texture2D> func = delegate(int imageIndex)
			{
				//IL_0097: Unknown result type (might be due to invalid IL or missing references)
				//IL_009e: Expected O, but got Unknown
				if (imageIndex < 0 || imageIndex >= images.Length)
				{
					return (Texture2D)null;
				}
				if (texCache.TryGetValue(imageIndex, out var value))
				{
					return value;
				}
				GLTFImage gLTFImage = images[imageIndex];
				if (gLTFImage.bufferView < 0 || gLTFImage.bufferView >= bufferViews.Length)
				{
					return (Texture2D)null;
				}
				GLTFBufferView gLTFBufferView = bufferViews[gLTFImage.bufferView];
				if (gLTFBufferView.byteOffset + gLTFBufferView.byteLength > binData.Length)
				{
					return (Texture2D)null;
				}
				byte[] array16 = new byte[gLTFBufferView.byteLength];
				Buffer.BlockCopy(binData, gLTFBufferView.byteOffset, array16, 0, gLTFBufferView.byteLength);
				Texture2D val7 = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!ImageConversion.LoadImage(val7, array16))
				{
					Object.Destroy((Object)(object)val7);
					return (Texture2D)null;
				}
				((Object)val7).name = gLTFImage.name ?? $"img_{imageIndex}";
				((Texture)val7).wrapMode = (TextureWrapMode)0;
				((Texture)val7).filterMode = (FilterMode)1;
				texCache[imageIndex] = val7;
				return val7;
			};
			Mesh[] array6 = (Mesh[])(object)new Mesh[array2.Length];
			Material[][] array7 = new Material[array2.Length][];
			Vector3[] array8 = (Vector3[])(object)new Vector3[array2.Length];
			for (int num = 0; num < array2.Length; num++)
			{
				GLTFMesh gLTFMesh = array2[num];
				Mesh val2 = new Mesh
				{
					name = (gLTFMesh.name ?? $"Mesh_{num}")
				};
				if (gLTFMesh.primitives != null && gLTFMesh.primitives.Length != 0)
				{
					List<Vector3> list = new List<Vector3>();
					List<Vector3> list2 = new List<Vector3>();
					List<Vector2> list3 = new List<Vector2>();
					List<int[]> list4 = new List<int[]>();
					List<Material> list5 = new List<Material>();
					for (int num2 = 0; num2 < gLTFMesh.primitives.Length; num2++)
					{
						GLTFPrimitive gLTFPrimitive = gLTFMesh.primitives[num2];
						int count = list.Count;
						GLTFAttributes attributes = gLTFPrimitive.attributes;
						Vector3[] array9 = ((attributes != null && attributes.POSITION >= 0 && gLTFPrimitive.attributes.POSITION < array.Length) ? ReadVec3Accessor(array[gLTFPrimitive.attributes.POSITION], bufferViews, binData) : null);
						GLTFAttributes attributes2 = gLTFPrimitive.attributes;
						Vector3[] array10 = ((attributes2 != null && attributes2.NORMAL >= 0 && gLTFPrimitive.attributes.NORMAL < array.Length) ? ReadVec3Accessor(array[gLTFPrimitive.attributes.NORMAL], bufferViews, binData) : null);
						GLTFAttributes attributes3 = gLTFPrimitive.attributes;
						Vector2[] array11 = ((attributes3 != null && attributes3.TEXCOORD_0 >= 0 && gLTFPrimitive.attributes.TEXCOORD_0 < array.Length) ? ReadVec2Accessor(array[gLTFPrimitive.attributes.TEXCOORD_0], bufferViews, binData) : null);
						if (array9 != null)
						{
							list.AddRange(array9);
							if (array10 != null && array10.Length == array9.Length)
							{
								list2.AddRange(array10);
							}
							else
							{
								for (int num3 = 0; num3 < array9.Length; num3++)
								{
									list2.Add(Vector3.up);
								}
							}
							if (array11 != null && array11.Length == array9.Length)
							{
								list3.AddRange(array11);
							}
							else
							{
								for (int num4 = 0; num4 < array9.Length; num4++)
								{
									list3.Add(Vector2.zero);
								}
							}
						}
						if (gLTFPrimitive.indices >= 0 && gLTFPrimitive.indices < array.Length)
						{
							int[] array12 = ReadIndicesAccessor(array[gLTFPrimitive.indices], bufferViews, binData);
							if (array12 != null)
							{
								int[] array13 = new int[array12.Length];
								for (int num5 = 0; num5 < array12.Length; num5++)
								{
									array13[num5] = array12[num5] + count;
								}
								list4.Add(array13);
							}
						}
						if (gLTFPrimitive.material >= 0 && gLTFPrimitive.material < array3.Length)
						{
							GLTFMaterial gLTFMaterial = array3[gLTFPrimitive.material];
							Texture2D baseTexture = null;
							int num6 = gLTFMaterial.pbrMetallicRoughness?.baseColorTexture?.index ?? (-1);
							if (num6 >= 0 && num6 < array5.Length)
							{
								baseTexture = func(array5[num6].source);
							}
							list5.Add(CreateMaterial(gLTFMaterial, shader, baseTexture));
						}
						else
						{
							list5.Add(new Material(shader)
							{
								color = Color.white
							});
						}
					}
					if (list.Count > 65535)
					{
						val2.indexFormat = (IndexFormat)1;
					}
					Vector3 val3 = Vector3.zero;
					if (list.Count > 0)
					{
						Vector3 val4 = list[0];
						Vector3 val5 = list[0];
						for (int num7 = 1; num7 < list.Count; num7++)
						{
							val4 = Vector3.Min(val4, list[num7]);
							val5 = Vector3.Max(val5, list[num7]);
						}
						val3 = (val4 + val5) * 0.5f;
						for (int num8 = 0; num8 < list.Count; num8++)
						{
							List<Vector3> list6 = list;
							int index = num8;
							list6[index] -= val3;
						}
					}
					array8[num] = val3;
					val2.SetVertices(list);
					val2.SetNormals(list2);
					val2.SetUVs(0, list3);
					val2.subMeshCount = list4.Count;
					for (int num9 = 0; num9 < list4.Count; num9++)
					{
						val2.SetTriangles(list4[num9], num9);
					}
					array7[num] = list5.ToArray();
				}
				val2.RecalculateNormals();
				val2.RecalculateBounds();
				array6[num] = val2;
			}
			GameObject[] array14 = (GameObject[])(object)new GameObject[array4.Length];
			for (int num10 = 0; num10 < array4.Length; num10++)
			{
				array14[num10] = new GameObject(array4[num10].name ?? $"Node_{num10}");
				GLTFNode gLTFNode = array4[num10];
				if (gLTFNode.translation != null && gLTFNode.translation.Length == 3)
				{
					array14[num10].transform.localPosition = new Vector3(gLTFNode.translation[0], gLTFNode.translation[1], gLTFNode.translation[2]);
				}
				if (gLTFNode.rotation != null && gLTFNode.rotation.Length == 4)
				{
					array14[num10].transform.localRotation = new Quaternion(gLTFNode.rotation[0], gLTFNode.rotation[1], gLTFNode.rotation[2], gLTFNode.rotation[3]);
				}
				if (gLTFNode.scale != null && gLTFNode.scale.Length == 3)
				{
					array14[num10].transform.localScale = new Vector3(gLTFNode.scale[0], gLTFNode.scale[1], gLTFNode.scale[2]);
				}
			}
			for (int num11 = 0; num11 < array4.Length; num11++)
			{
				if (array4[num11].children == null)
				{
					continue;
				}
				int[] children = array4[num11].children;
				foreach (int num12 in children)
				{
					if (num12 >= 0 && num12 < array14.Length)
					{
						array14[num12].transform.SetParent(array14[num11].transform, false);
					}
				}
			}
			for (int num13 = 0; num13 < array4.Length; num13++)
			{
				GLTFNode gLTFNode2 = array4[num13];
				GameObject val6 = array14[num13];
				if (gLTFNode2.mesh >= 0 && gLTFNode2.mesh < array6.Length)
				{
					if (gLTFNode2.translation == null || gLTFNode2.translation.Length < 3)
					{
						Transform transform = val6.transform;
						transform.localPosition += array8[gLTFNode2.mesh];
					}
					val6.AddComponent<MeshFilter>().sharedMesh = array6[gLTFNode2.mesh];
					((Renderer)val6.AddComponent<MeshRenderer>()).sharedMaterials = array7[gLTFNode2.mesh];
				}
			}
			bool flag = false;
			GLTFScene[] array15 = gLTFRoot.scenes ?? new GLTFScene[0];
			foreach (GLTFScene gLTFScene in array15)
			{
				if (gLTFScene.nodes == null)
				{
					continue;
				}
				int[] children = gLTFScene.nodes;
				foreach (int num15 in children)
				{
					if (num15 >= 0 && num15 < array14.Length)
					{
						array14[num15].transform.SetParent(val.transform, false);
						flag = true;
					}
				}
			}
			if (!flag)
			{
				for (int num16 = 0; num16 < array14.Length; num16++)
				{
					if ((Object)(object)array14[num16].transform.parent == (Object)null)
					{
						array14[num16].transform.SetParent(val.transform, false);
					}
				}
			}
			return val;
		}

		private static Vector3[] ReadVec3Accessor(GLTFAccessor accessor, GLTFBufferView[] bufferViews, byte[] binData)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (accessor == null || accessor.bufferView < 0 || accessor.bufferView >= bufferViews.Length)
			{
				return null;
			}
			GLTFBufferView gLTFBufferView = bufferViews[accessor.bufferView];
			int num = gLTFBufferView.byteOffset + accessor.byteOffset;
			int count = accessor.count;
			int num2 = ((gLTFBufferView.byteStride > 0) ? gLTFBufferView.byteStride : 12);
			Vector3[] array = (Vector3[])(object)new Vector3[count];
			for (int i = 0; i < count; i++)
			{
				int num3 = num + i * num2;
				if (num3 + 12 <= binData.Length)
				{
					array[i] = new Vector3(BitConverter.ToSingle(binData, num3), BitConverter.ToSingle(binData, num3 + 4), BitConverter.ToSingle(binData, num3 + 8));
				}
			}
			return array;
		}

		private static Vector2[] ReadVec2Accessor(GLTFAccessor accessor, GLTFBufferView[] bufferViews, byte[] binData)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			if (accessor == null || accessor.bufferView < 0 || accessor.bufferView >= bufferViews.Length)
			{
				return null;
			}
			GLTFBufferView gLTFBufferView = bufferViews[accessor.bufferView];
			int num = gLTFBufferView.byteOffset + accessor.byteOffset;
			int count = accessor.count;
			int num2 = ((gLTFBufferView.byteStride > 0) ? gLTFBufferView.byteStride : 8);
			Vector2[] array = (Vector2[])(object)new Vector2[count];
			for (int i = 0; i < count; i++)
			{
				int num3 = num + i * num2;
				if (num3 + 8 <= binData.Length)
				{
					array[i] = new Vector2(BitConverter.ToSingle(binData, num3), 1f - BitConverter.ToSingle(binData, num3 + 4));
				}
			}
			return array;
		}

		private static int[] ReadIndicesAccessor(GLTFAccessor accessor, GLTFBufferView[] bufferViews, byte[] binData)
		{
			if (accessor == null || accessor.bufferView < 0 || accessor.bufferView >= bufferViews.Length)
			{
				return null;
			}
			GLTFBufferView gLTFBufferView = bufferViews[accessor.bufferView];
			int num = gLTFBufferView.byteOffset + accessor.byteOffset;
			int count = accessor.count;
			int[] array = new int[count];
			if (accessor.componentType == 5123)
			{
				int num2 = ((gLTFBufferView.byteStride > 0) ? gLTFBufferView.byteStride : 2);
				for (int i = 0; i < count; i++)
				{
					int num3 = num + i * num2;
					if (num3 + 2 <= binData.Length)
					{
						array[i] = BitConverter.ToUInt16(binData, num3);
					}
				}
			}
			else if (accessor.componentType == 5125)
			{
				int num4 = ((gLTFBufferView.byteStride > 0) ? gLTFBufferView.byteStride : 4);
				for (int j = 0; j < count; j++)
				{
					int num5 = num + j * num4;
					if (num5 + 4 <= binData.Length)
					{
						array[j] = BitConverter.ToInt32(binData, num5);
					}
				}
			}
			else if (accessor.componentType == 5121)
			{
				for (int k = 0; k < count; k++)
				{
					int num6 = num + k;
					if (num6 < binData.Length)
					{
						array[k] = binData[num6];
					}
				}
			}
			return array;
		}

		private static Material CreateMaterial(GLTFMaterial mat, Shader shader, Texture2D baseTexture)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: 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)
			Material val = new Material(shader ?? FindValidShader())
			{
				name = (mat.name ?? "DropCrateMat")
			};
			if ((Object)(object)baseTexture != (Object)null)
			{
				val.mainTexture = (Texture)(object)baseTexture;
				if (val.HasProperty("_MainTex"))
				{
					val.SetTexture("_MainTex", (Texture)(object)baseTexture);
				}
				if (val.HasProperty("_BaseMap"))
				{
					val.SetTexture("_BaseMap", (Texture)(object)baseTexture);
				}
				if (val.HasProperty("_Albedo"))
				{
					val.SetTexture("_Albedo", (Texture)(object)baseTexture);
				}
			}
			Color val2 = Color.white;
			if (mat.pbrMetallicRoughness != null)
			{
				GLTFPBR pbrMetallicRoughness = mat.pbrMetallicRoughness;
				if (pbrMetallicRoughness.baseColorFactor != null && pbrMetallicRoughness.baseColorFactor.Length == 4)
				{
					Color white = default(Color);
					((Color)(ref white))..ctor(pbrMetallicRoughness.baseColorFactor[0], pbrMetallicRoughness.baseColorFactor[1], pbrMetallicRoughness.baseColorFactor[2], pbrMetallicRoughness.baseColorFactor[3]);
					if (white.a <= 0.01f || ((Object)(object)baseTexture != (Object)null && white.r <= 0.08f && white.g <= 0.08f && white.b <= 0.08f))
					{
						white = Color.white;
					}
					val2 = white;
				}
				if (pbrMetallicRoughness.metallicFactor.HasValue && val.HasProperty("_Metallic"))
				{
					val.SetFloat("_Metallic", Mathf.Clamp01(pbrMetallicRoughness.metallicFactor.Value));
				}
				if (pbrMetallicRoughness.roughnessFactor.HasValue)
				{
					float num = Mathf.Clamp01(1f - pbrMetallicRoughness.roughnessFactor.Value);
					if (val.HasProperty("_Glossiness"))
					{
						val.SetFloat("_Glossiness", num);
					}
					if (val.HasProperty("_Smoothness"))
					{
						val.SetFloat("_Smoothness", num);
					}
				}
			}
			val.color = val2;
			if (val.HasProperty("_Color"))
			{
				val.SetColor("_Color", val2);
			}
			if (val.HasProperty("_BaseColor"))
			{
				val.SetColor("_BaseColor", val2);
			}
			if (val.HasProperty("_Cull"))
			{
				val.SetInt("_Cull", 0);
			}
			val.renderQueue = 2000;
			return val;
		}
	}
	public class DropCrateManager : MonoBehaviour
	{
		private static readonly Dictionary<ItemDrop, float> s_playerDropTimes = new Dictionary<ItemDrop, float>();

		private static readonly MethodInfo s_containerSave = typeof(Container).GetMethod("Save", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldRef<List<ItemDrop>> s_instancesRef = AccessTools.StaticFieldRefAccess<List<ItemDrop>>(AccessTools.Field(typeof(ItemDrop), "s_instances"));

		private float m_lastScanTime;

		public static void RegisterPlayerDrop(ItemDrop drop)
		{
			if ((Object)(object)drop != (Object)null)
			{
				s_playerDropTimes[drop] = Time.time;
			}
		}

		public static bool IsUnderGracePeriod(ItemDrop drop)
		{
			if ((Object)(object)drop == (Object)null)
			{
				return false;
			}
			if (s_playerDropTimes.TryGetValue(drop, out var value))
			{
				if (Time.time - value < DropCrateConfig.PlayerDropGracePeriodSeconds.Value)
				{
					return true;
				}
				s_playerDropTimes.Remove(drop);
			}
			return false;
		}

		private void Update()
		{
			if (DropCrateConfig.Enabled.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)ZNetScene.instance == (Object)null) && Time.time - m_lastScanTime >= DropCrateConfig.ScanIntervalSeconds.Value)
			{
				m_lastScanTime = Time.time;
				ScanAndConsolidate();
			}
		}

		public static void ScanAndConsolidate(int? overrideThreshold = null)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			Vector3 position = ((Component)localPlayer).transform.position;
			float value = DropCrateConfig.ScanRadius.Value;
			float num = value * value;
			CleanupStaleDrops();
			List<ItemDrop> list = new List<ItemDrop>();
			List<ItemDrop> list2 = ((s_instancesRef != null) ? s_instancesRef.Invoke() : null);
			if (list2 != null)
			{
				for (int i = 0; i < list2.Count; i++)
				{
					ItemDrop val = list2[i];
					if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy && (!((Object)(object)((Component)val).transform.parent != (Object)null) || !((Object)(object)((Component)val).GetComponentInParent<Character>() != (Object)null)) && !IsUnderGracePeriod(val))
					{
						Vector3 position2 = ((Component)val).transform.position;
						Vector3 val2 = position2 - position;
						if (!(((Vector3)(ref val2)).sqrMagnitude > num) && (!DropCrateConfig.RespectWards.Value || !IsProtectedByActiveWard(position2)) && val.m_itemData != null && val.m_itemData.m_stack > 0)
						{
							list.Add(val);
						}
					}
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			if (DropCrateConfig.SweepIntoExistingCrates.Value && DropCrateController.s_activeCrates.Count > 0)
			{
				float value2 = DropCrateConfig.ClusterRadius.Value;
				for (int num2 = DropCrateController.s_activeCrates.Count - 1; num2 >= 0; num2--)
				{
					DropCrateController dropCrateController = DropCrateController.s_activeCrates[num2];
					if (!((Object)(object)dropCrateController == (Object)null) && !((Object)(object)dropCrateController.Container == (Object)null))
					{
						Inventory inventory = dropCrateController.Container.GetInventory();
						if (inventory != null)
						{
							Vector3 position3 = ((Component)dropCrateController).transform.position;
							int num3 = 0;
							for (int num4 = list.Count - 1; num4 >= 0; num4--)
							{
								ItemDrop val3 = list[num4];
								if ((Object)(object)val3 == (Object)null)
								{
									list.RemoveAt(num4);
								}
								else if (Vector3.Distance(((Component)val3).transform.position, position3) <= value2 && TryAddItemToInventory(inventory, val3))
								{
									num3++;
									list.RemoveAt(num4);
								}
							}
							if (num3 > 0)
							{
								SaveContainer(dropCrateController.Container);
								dropCrateController.UpdatePinAndName();
								PlaySweepFeedback(position3);
							}
						}
					}
				}
			}
			int num5 = (overrideThreshold.HasValue ? Mathf.Max(1, overrideThreshold.Value) : DropCrateConfig.ClusterItemThreshold.Value);
			if (list.Count < num5)
			{
				return;
			}
			float value3 = DropCrateConfig.ClusterRadius.Value;
			HashSet<ItemDrop> hashSet = new HashSet<ItemDrop>(list);
			while (hashSet.Count >= num5)
			{
				HashSet<ItemDrop>.Enumerator enumerator = hashSet.GetEnumerator();
				if (!enumerator.MoveNext())
				{
					break;
				}
				ItemDrop current = enumerator.Current;
				hashSet.Remove(current);
				List<ItemDrop> list3 = new List<ItemDrop> { current };
				Vector3 position4 = ((Component)current).transform.position;
				List<ItemDrop> list4 = new List<ItemDrop>();
				foreach (ItemDrop item in hashSet)
				{
					if ((Object)(object)item != (Object)null && Vector3.Distance(((Component)item).transform.position, position4) <= value3)
					{
						list4.Add(item);
					}
				}
				foreach (ItemDrop item2 in list4)
				{
					list3.Add(item2);
					hashSet.Remove(item2);
				}
				if (list3.Count >= num5)
				{
					ConsolidateClusterIntoNewCrate(list3);
				}
			}
		}

		private static void ConsolidateClusterIntoNewCrate(List<ItemDrop> cluster)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_0062: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: 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)
			if (cluster == null || cluster.Count == 0)
			{
				return;
			}
			Vector3 val = Vector3.zero;
			int num = 0;
			for (int i = 0; i < cluster.Count; i++)
			{
				if ((Object)(object)cluster[i] != (Object)null)
				{
					val += ((Component)cluster[i]).transform.position;
					num++;
				}
			}
			if (num == 0)
			{
				return;
			}
			Vector3 val2 = val / (float)num;
			float num2 = default(float);
			if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGroundHeight(val2, ref num2))
			{
				val2.y = Mathf.Max(num2 + 0.15f, val2.y);
			}
			GameObject val3 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("DFG_DropCrate") : null);
			if ((Object)(object)val3 == (Object)null)
			{
				DropCratePlugin.Log.LogError((object)"DropCrate: Prefab DFG_DropCrate not found!");
				return;
			}
			GameObject obj = Object.Instantiate<GameObject>(val3, val2, Quaternion.identity);
			Container component = obj.GetComponent<Container>();
			DropCrateController component2 = obj.GetComponent<DropCrateController>();
			if (!((Object)(object)component != (Object)null) || component.GetInventory() == null)
			{
				return;
			}
			Inventory inventory = component.GetInventory();
			int num3 = 0;
			for (int j = 0; j < cluster.Count; j++)
			{
				ItemDrop val4 = cluster[j];
				if (!((Object)(object)val4 == (Object)null) && TryAddItemToInventory(inventory, val4))
				{
					num3++;
				}
			}
			SaveContainer(component);
			if ((Object)(object)component2 != (Object)null)
			{
				component2.UpdatePinAndName();
			}
			PlaySweepFeedback(val2);
			DropCratePlugin.Log.LogInfo((object)$"DropCrate: Swept {num3} items into new Drop Crate at {val2}.");
		}

		public static bool TryAddItemToInventory(Inventory inv, ItemDrop drop)
		{
			if (inv == null || (Object)(object)drop == (Object)null || drop.m_itemData == null || drop.m_itemData.m_stack <= 0)
			{
				return false;
			}
			ItemData itemData = drop.m_itemData;
			EnsureDropPrefab(itemData);
			int stack = itemData.m_stack;
			if (inv.AddItem(itemData))
			{
				DestroyItemDrop(drop);
				return true;
			}
			if (itemData.m_stack < stack && itemData.m_stack > 0)
			{
				drop.m_itemData.m_stack = itemData.m_stack;
				ZNetView component = ((Component)drop).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid())
				{
					component.GetZDO().Set(ZDOVars.s_stack, itemData.m_stack, false);
				}
				return true;
			}
			return false;
		}

		private static void DestroyItemDrop(ItemDrop drop)
		{
			if ((Object)(object)drop == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)drop).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid() && (Object)(object)ZNetScene.instance != (Object)null)
			{
				if (!component.IsOwner())
				{
					component.ClaimOwnership();
				}
				ZNetScene.instance.Destroy(((Component)drop).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)((Component)drop).gameObject);
			}
		}

		public static void EnsureDropPrefab(ItemData item)
		{
			if (item == null || (Object)(object)item.m_dropPrefab != (Object)null || (Object)(object)ObjectDB.instance == (Object)null || item.m_shared == null)
			{
				return;
			}
			foreach (GameObject item2 in ObjectDB.instance.m_items)
			{
				if (!((Object)(object)item2 == (Object)null))
				{
					ItemDrop component = item2.GetComponent<ItemDrop>();
					if ((Object)(object)component != (Object)null && component.m_itemData?.m_shared != null && component.m_itemData.m_shared.m_name == item.m_shared.m_name)
					{
						item.m_dropPrefab = item2;
						break;
					}
				}
			}
		}

		public static void SaveContainer(Container c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return;
			}
			try
			{
				s_containerSave?.Invoke(c, null);
			}
			catch
			{
			}
		}

		public static bool IsProtectedByActiveWard(Vector3 point)
		{
			//IL_0000: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			Collider[] array = Physics.OverlapSphere(point, 32f);
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] == (Object)null)
				{
					continue;
				}
				PrivateArea componentInParent = ((Component)array[i]).GetComponentInParent<PrivateArea>();
				if (!((Object)(object)componentInParent == (Object)null))
				{
					ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetBool(ZDOVars.s_enabled, false) && Vector3.Distance(point, ((Component)componentInParent).transform.position) <= componentInParent.m_radius)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static void CleanupStaleDrops()
		{
			if (s_playerDropTimes.Count == 0)
			{
				return;
			}
			float time = Time.time;
			List<ItemDrop> list = null;
			foreach (KeyValuePair<ItemDrop, float> s_playerDropTime in s_playerDropTimes)
			{
				if ((Object)(object)s_playerDropTime.Key == (Object)null || time - s_playerDropTime.Value > 60f)
				{
					if (list == null)
					{
						list = new List<ItemDrop>();
					}
					list.Add(s_playerDropTime.Key);
				}
			}
			if (list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					s_playerDropTimes.Remove(list[i]);
				}
			}
		}

		private static void PlaySweepFeedback(Vector3 pos)
		{
			//IL_0046: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (DropCrateConfig.PlayVfxOnSweep.Value && (Object)(object)ZNetScene.instance != (Object)null)
				{
					GameObject val = ZNetScene.instance.GetPrefab("vfx_ItemDrop") ?? ZNetScene.instance.GetPrefab("vfx_loot_spawn");
					if ((Object)(object)val != (Object)null)
					{
						Object.Instantiate<GameObject>(val, pos + Vector3.up * 0.4f, Quaternion.identity);
					}
				}
				if (DropCrateConfig.PlaySoundOnSweep.Value && (Object)(object)ZNetScene.instance != (Object)null)
				{
					GameObject val2 = ZNetScene.instance.GetPrefab("sfx_chest_open") ?? ZNetScene.instance.GetPrefab("sfx_build_hammer_wood");
					if ((Object)(object)val2 != (Object)null)
					{
						Object.Instantiate<GameObject>(val2, pos + Vector3.up * 0.4f, Quaternion.identity);
					}
				}
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "OnPlayerDrop")]
	internal static class ItemDropOnPlayerDropPatch
	{
		private static void Postfix(ItemDrop __instance)
		{
			if ((Object)(object)__instance != (Object)null)
			{
				DropCrateManager.RegisterPlayerDrop(__instance);
			}
		}
	}
	[BepInPlugin("com.dfg.dropcrate", "DropCrate", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class DropCratePlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.dfg.dropcrate";

		public const string PluginName = "DropCrate";

		public const string PluginVersion = "1.0.0";

		private static bool s_pinRegistered;

		private Harmony m_harmony;

		public static DropCratePlugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		public static PinType DropCratePinType { get; set; } = (PinType)3;

		public static string PluginPath => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

		public static string PluginFile(string fileName)
		{
			if (string.IsNullOrEmpty(fileName))
			{
				return string.Empty;
			}
			return Path.Combine(PluginPath, fileName);
		}

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			DropCrateConfig.Init(((BaseUnityPlugin)this).Config);
			DropCratePrefabs.Init();
			try
			{
				m_harmony = new Harmony("com.dfg.dropcrate");
				m_harmony.PatchAll();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("DropCrate: failed to apply Harmony patches: " + ex));
			}
			((Component)this).gameObject.AddComponent<DropCrateManager>();
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DropCrateSweepCommand());
			Log.LogInfo((object)"DropCrate v1.0.0 initialized successfully.");
		}

		public static void RegisterCustomPin()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			if (s_pinRegistered || (Object)(object)Minimap.instance == (Object)null)
			{
				return;
			}
			try
			{
				Sprite val = null;
				string path = PluginFile("icon.png");
				if (File.Exists(path))
				{
					byte[] array = File.ReadAllBytes(path);
					Texture2D val2 = new Texture2D(2, 2, (TextureFormat)4, false);
					if (ImageConversion.LoadImage(val2, array))
					{
						val = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f), 100f);
					}
				}
				if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
				{
					GameObject prefab = ZNetScene.instance.GetPrefab("piece_chest_wood");
					val = ((prefab == null) ? null : prefab.GetComponent<Piece>()?.m_icon);
				}
				if ((Object)(object)val != (Object)null)
				{
					PinType val3 = (PinType)Minimap.instance.m_icons.Count;
					SpriteData item = new SpriteData
					{
						m_name = val3,
						m_icon = val
					};
					Minimap.instance.m_icons.Add(item);
					DropCratePinType = val3;
					s_pinRegistered = true;
					Log.LogInfo((object)"DropCrate: Registered custom Minimap pin sprite.");
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("DropCrate: Failed to register custom pin icon, defaulting to Icon3: " + ex.Message));
				DropCratePinType = (PinType)3;
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = m_harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	[HarmonyPatch(typeof(Minimap), "Start")]
	internal static class MinimapStartPatch
	{
		private static void Postfix()
		{
			DropCratePlugin.RegisterCustomPin();
		}
	}
	internal sealed class DropCrateSweepCommand : ConsoleCommand
	{
		public override string Name => "dropcrate_sweep";

		public override string Help => "DropCrate: Manually trigger an immediate scan and consolidation of nearby ground items. Usage: dropcrate_sweep [minThreshold]";

		public override void Run(string[] args)
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				Console.instance.Print("dropcrate_sweep: No local player found.");
				return;
			}
			int num = DropCrateConfig.ClusterItemThreshold.Value;
			if (args != null && args.Length > 1 && int.TryParse(args[1], out var result))
			{
				num = Mathf.Max(1, result);
			}
			DropCrateManager.ScanAndConsolidate(num);
			Console.instance.Print($"DropCrate: Sweep executed (threshold: {num} items).");
		}
	}
	public static class DropCratePrefabs
	{
		public const string DropCratePrefabName = "DFG_DropCrate";

		private static bool s_registered;

		public static void Init()
		{
			PrefabManager.OnVanillaPrefabsAvailable += RegisterPrefabs;
			LocalizationManager.Instance.AddToken("dfg_dropcrate_name", "Drop Crate", false);
			LocalizationManager.Instance.AddToken("dfg_dropcrate_desc", "Temporary salvage crate consolidating loose items to reduce world lag.", false);
		}

		private static void RegisterPrefabs()
		{
			if (s_registered)
			{
				return;
			}
			s_registered = true;
			try
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab("piece_chest_wood");
				if ((Object)(object)prefab == (Object)null)
				{
					DropCratePlugin.Log.LogError((object)"DropCrate: Could not find piece_chest_wood source prefab!");
					return;
				}
				GameObject val = PrefabManager.Instance.CreateClonedPrefab("DFG_DropCrate", prefab);
				((Object)val).name = "DFG_DropCrate";
				Piece component = val.GetComponent<Piece>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_name = "$dfg_dropcrate_name";
					component.m_description = "$dfg_dropcrate_desc";
					component.m_canBeRemoved = false;
				}
				Container component2 = val.GetComponent<Container>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.m_name = "Drop Crate";
					component2.m_width = DropCrateConfig.CrateWidth.Value;
					component2.m_height = DropCrateConfig.CrateHeight.Value;
					component2.m_checkGuardStone = false;
					component2.m_autoDestroyEmpty = false;
				}
				WearNTear component3 = val.GetComponent<WearNTear>();
				if ((Object)(object)component3 != (Object)null)
				{
					component3.m_noSupportWear = false;
					component3.m_noRoofWear = false;
					component3.m_burnable = false;
					component3.m_ashDamageImmune = true;
					component3.m_health = 100000f;
				}
				val.AddComponent<DropCrateController>();
				PrefabManager.Instance.AddPrefab(val);
				DropCratePlugin.Log.LogInfo((object)"DropCrate: Successfully registered DFG_DropCrate prefab.");
			}
			catch (Exception ex)
			{
				DropCratePlugin.Log.LogError((object)("DropCrate: Failed to register DFG_DropCrate prefab: " + ex));
			}
		}
	}
}