Decompiled source of MagicStorageValheim v1.1.9

MagicStorageValheim.dll

Decompiled 21 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("MagicStorageValheim")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.1.9.0")]
[assembly: AssemblyInformationalVersion("1.1.9")]
[assembly: AssemblyProduct("MagicStorageValheim")]
[assembly: AssemblyTitle("MagicStorageValheim")]
[assembly: AssemblyVersion("1.1.9.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 MagicStorageValheim
{
	[BepInPlugin("flambo.magicstorage", "Magic Storage Valheim", "1.1.9")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class MagicStoragePlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "flambo.magicstorage";

		public const string PluginName = "Magic Storage Valheim";

		public const string PluginVersion = "1.1.9";

		internal static MagicStoragePlugin Instance;

		internal static ConfigEntry<KeyboardShortcut> OpenKey;

		internal static ConfigEntry<float> NetworkRadius;

		internal static ConfigEntry<int> UnitWidth;

		internal static ConfigEntry<int> UnitHeight;

		internal static ConfigEntry<bool> RepairOnDeposit;

		internal static ConfigEntry<float> WindowX;

		internal static ConfigEntry<float> WindowY;

		internal static ConfigEntry<float> WindowWidth;

		internal static ConfigEntry<float> WindowHeight;

		internal static ManualLogSource Log;

		private StorageGui _gui;

		private readonly Harmony _harmony = new Harmony("flambo.magicstorage");

		private bool _piecesRegistered;

		internal void OpenStorageCore(StorageCore core)
		{
			if ((Object)(object)core != (Object)null)
			{
				_gui?.OpenCore(core);
			}
		}

		private void Awake()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = Logger.CreateLogSource("Magic Storage Valheim");
			OpenKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "OpenKey", new KeyboardShortcut((KeyCode)103, Array.Empty<KeyCode>()), "Open Magic Storage while looking at a Storage Core.");
			NetworkRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Storage", "NetworkRadius", 30f, "Maximum distance from the Storage Core to include Storage Units.");
			UnitWidth = ((BaseUnityPlugin)this).Config.Bind<int>("Storage", "UnitWidth", 4, "Storage Unit inventory width.");
			UnitHeight = ((BaseUnityPlugin)this).Config.Bind<int>("Storage", "UnitHeight", 4, "Storage Unit inventory height.");
			RepairOnDeposit = ((BaseUnityPlugin)this).Config.Bind<bool>("Storage", "RepairOnDeposit", true, "Repair damaged equipment when deposited, but only when the required nearby crafting station and level are available.");
			WindowX = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowX", 8f, "Saved Magic Storage window X position.");
			WindowY = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowY", -1f, "Saved Magic Storage window Y position. -1 uses the default position.");
			WindowWidth = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowWidth", 860f, "Saved Magic Storage window width.");
			WindowHeight = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowHeight", 600f, "Saved Magic Storage window height.");
			PrefabManager.OnVanillaPrefabsAvailable += RegisterPieces;
			((MonoBehaviour)this).StartCoroutine(RegisterPiecesWhenReady());
			_gui = ((Component)this).gameObject.AddComponent<StorageGui>();
			_harmony.PatchAll();
			Log.LogInfo((object)"Magic Storage Valheim 1.1.9 loaded.");
		}

		private void OnGUI()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				return;
			}
			try
			{
				if (!((Object)(object)FejdStartup.instance == (Object)null))
				{
					GUIStyle val = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)6,
						fontSize = 14
					};
					val.normal.textColor = new Color(0.82f, 0.72f, 0.52f, 0.9f);
					GUIStyle val2 = val;
					GUI.Label(new Rect(12f, (float)Screen.height - 34f, 300f, 24f), "Magic Storage 1.1.9", val2);
				}
			}
			catch
			{
			}
		}

		private IEnumerator RegisterPiecesWhenReady()
		{
			while (!_piecesRegistered)
			{
				GameObject chest = null;
				try
				{
					chest = PrefabManager.Instance.GetPrefab("piece_chest_wood");
				}
				catch
				{
				}
				if ((Object)(object)chest != (Object)null)
				{
					RegisterPieces();
					break;
				}
				yield return null;
			}
		}

		private void RegisterPieces()
		{
			if (_piecesRegistered)
			{
				return;
			}
			try
			{
				Log.LogInfo((object)"Registering Magic Storage build pieces...");
				CreatePiece("MagicStorageCore", "piece_chest_wood", "Storage Core", "A magical heart that links nearby Storage Units.");
				CreatePiece("MagicStorageUnit", "piece_chest_wood", "Storage Unit", "Adds storage space to a nearby Storage Core.");
				CreateWirelessRemote();
				_piecesRegistered = true;
				Log.LogInfo((object)"v1.1.2: Submitted visually distinct Storage Core and Storage Unit to Hammer with Storage usage tag.");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to register Magic Storage pieces: {arg}");
			}
			finally
			{
				PrefabManager.OnVanillaPrefabsAvailable -= RegisterPieces;
			}
		}

		private void CreateWirelessRemote()
		{
			//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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			ItemConfig val = new ItemConfig
			{
				Name = "Wireless Storage Remote",
				Description = "Use: open linked Magic Storage. Shift + Use while looking at a Storage Core: link/relink. Ctrl + Use: consume the next boss trophy to increase wireless range.",
				CraftingStation = CraftingStations.Workbench,
				Amount = 1,
				StackSize = 1
			};
			val.AddRequirement("FineWood", 10, 0);
			val.AddRequirement("SurtlingCore", 2, 0);
			val.AddRequirement("GreydwarfEye", 5, 0);
			val.AddRequirement("Bronze", 1, 0);
			CustomItem val2 = new CustomItem("MagicStorageWirelessRemote", "Wishbone", val);
			ItemDrop itemDrop = val2.ItemDrop;
			if (itemDrop?.m_itemData?.m_shared != null)
			{
				itemDrop.m_itemData.m_shared.m_name = "Wireless Storage Remote";
				itemDrop.m_itemData.m_shared.m_description = val.Description;
				itemDrop.m_itemData.m_shared.m_maxStackSize = 1;
				itemDrop.m_itemData.m_shared.m_equipStatusEffect = null;
				itemDrop.m_itemData.m_shared.m_teleportable = true;
			}
			BuildTwinRavenRemoteLook(val2.ItemPrefab);
			try
			{
				Sprite val3 = RenderManager.Instance.Render(val2.ItemPrefab, RenderManager.IsometricRotation);
				if (itemDrop?.m_itemData?.m_shared != null && (Object)(object)val3 != (Object)null)
				{
					itemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val3 };
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("v1.1.2: could not render twin-raven remote icon: " + ex.Message));
			}
			ItemManager.Instance.AddItem(val2);
			Log.LogInfo((object)"v1.1.2: Wireless Storage Remote registered (Workbench recipe; boss-trophy range upgrades).");
		}

		private static void BuildTwinRavenRemoteLook(GameObject prefab)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0064: 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_0086: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)prefab == (Object)null))
			{
				Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val in componentsInChildren)
				{
					val.enabled = false;
				}
				GameObject val2 = new GameObject("HuginnMuninnArtifact");
				val2.transform.SetParent(prefab.transform, false);
				val2.transform.localPosition = Vector3.zero;
				val2.transform.localRotation = Quaternion.identity;
				val2.transform.localScale = Vector3.one;
				Material raven = MakeRemoteMaterial(new Color(0.025f, 0.03f, 0.045f, 1f), new Color(0.006f, 0.018f, 0.035f, 1f));
				Material wing = MakeRemoteMaterial(new Color(0.04f, 0.05f, 0.075f, 1f), new Color(0.008f, 0.025f, 0.055f, 1f));
				Material beak = MakeRemoteMaterial(new Color(0.1f, 0.095f, 0.08f, 1f), Color.black);
				Material val3 = MakeRemoteMaterial(new Color(0.08f, 0.45f, 0.62f, 1f), new Color(0.08f, 0.55f, 0.82f, 1f));
				BuildRaven(val2.transform, new Vector3(-0.27f, 0.03f, 0f), 1f, raven, wing, beak, val3);
				BuildRaven(val2.transform, new Vector3(0.27f, 0.03f, 0f), -1f, raven, wing, beak, val3);
				GameObject val4 = GameObject.CreatePrimitive((PrimitiveType)0);
				((Object)val4).name = "MemoryThoughtCrystal";
				val4.transform.SetParent(val2.transform, false);
				val4.transform.localPosition = new Vector3(0f, 0.02f, 0f);
				val4.transform.localScale = new Vector3(0.16f, 0.16f, 0.16f);
				Object.DestroyImmediate((Object)(object)val4.GetComponent<Collider>());
				val4.GetComponent<Renderer>().material = val3;
				GameObject val5 = GameObject.CreatePrimitive((PrimitiveType)3);
				((Object)val5).name = "RavenPerch";
				val5.transform.SetParent(val2.transform, false);
				val5.transform.localPosition = new Vector3(0f, -0.17f, 0f);
				val5.transform.localScale = new Vector3(0.72f, 0.055f, 0.075f);
				Object.DestroyImmediate((Object)(object)val5.GetComponent<Collider>());
				val5.GetComponent<Renderer>().material = val3;
			}
		}

		private static void BuildRaven(Transform parent, Vector3 center, float facing, Material raven, Material wing, Material beak, Material magic)
		{
			//IL_0037: 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_006c: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: 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)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: 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)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)val).name = ((facing > 0f) ? "HuginnBody" : "MuninnBody");
			val.transform.SetParent(parent, false);
			val.transform.localPosition = center + new Vector3(0f, 0f, 0f);
			val.transform.localScale = new Vector3(0.23f, 0.31f, 0.18f);
			Object.DestroyImmediate((Object)(object)val.GetComponent<Collider>());
			val.GetComponent<Renderer>().material = raven;
			GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)val2).name = ((facing > 0f) ? "HuginnHead" : "MuninnHead");
			val2.transform.SetParent(parent, false);
			val2.transform.localPosition = center + new Vector3(0.075f * facing, 0.19f, 0f);
			val2.transform.localScale = new Vector3(0.17f, 0.17f, 0.16f);
			Object.DestroyImmediate((Object)(object)val2.GetComponent<Collider>());
			val2.GetComponent<Renderer>().material = raven;
			GameObject val3 = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)val3).name = "Beak";
			val3.transform.SetParent(parent, false);
			val3.transform.localPosition = center + new Vector3(0.18f * facing, 0.19f, 0f);
			val3.transform.localScale = new Vector3(0.13f, 0.045f, 0.065f);
			val3.transform.localRotation = Quaternion.Euler(0f, 0f, (facing > 0f) ? (-8f) : 8f);
			Object.DestroyImmediate((Object)(object)val3.GetComponent<Collider>());
			val3.GetComponent<Renderer>().material = beak;
			for (int i = 0; i < 3; i++)
			{
				GameObject val4 = GameObject.CreatePrimitive((PrimitiveType)3);
				((Object)val4).name = "WingFeather";
				val4.transform.SetParent(parent, false);
				val4.transform.localPosition = center + new Vector3(-0.035f * facing, -0.015f - (float)i * 0.035f, 0.105f);
				val4.transform.localScale = new Vector3(0.25f - (float)i * 0.025f, 0.055f, 0.055f);
				val4.transform.localRotation = Quaternion.Euler(0f, 0f, ((facing > 0f) ? 28f : (-28f)) + (float)i * ((facing > 0f) ? 6f : (-6f)));
				Object.DestroyImmediate((Object)(object)val4.GetComponent<Collider>());
				val4.GetComponent<Renderer>().material = wing;
			}
			GameObject val5 = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)val5).name = "MagicEye";
			val5.transform.SetParent(parent, false);
			val5.transform.localPosition = center + new Vector3(0.115f * facing, 0.215f, -0.065f);
			val5.transform.localScale = Vector3.one * 0.025f;
			Object.DestroyImmediate((Object)(object)val5.GetComponent<Collider>());
			val5.GetComponent<Renderer>().material = magic;
		}

		private static Material MakeRemoteMaterial(Color baseColor, Color emission)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			Shader val = Shader.Find("Standard") ?? Shader.Find("Sprites/Default");
			Material val2 = new Material(val);
			if (val2.HasProperty("_Color"))
			{
				val2.color = baseColor;
			}
			if (val2.HasProperty("_BaseColor"))
			{
				val2.SetColor("_BaseColor", baseColor);
			}
			if (val2.HasProperty("_EmissionColor"))
			{
				if (((Color)(ref emission)).maxColorComponent > 0.001f)
				{
					val2.EnableKeyword("_EMISSION");
					val2.SetColor("_EmissionColor", emission);
				}
				else
				{
					val2.SetColor("_EmissionColor", Color.black);
				}
			}
			return val2;
		}

		private void CreatePiece(string prefabName, string basePrefab, string displayName, string description)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			PieceConfig val = new PieceConfig();
			val.Name = displayName;
			val.Description = description;
			val.PieceTable = PieceTables.Hammer;
			val.Category = PieceCategories.Misc;
			val.Usage = new string[1] { PieceUsages.Storage };
			val.Requirements = Array.Empty<RequirementConfig>();
			PieceConfig val2 = val;
			if (prefabName == "MagicStorageCore")
			{
				val2.AddRequirement("FineWood", 20, true);
				val2.AddRequirement("TrophyEikthyr", 1, true);
				val2.AddRequirement("TrophyTheElder", 1, true);
			}
			else
			{
				val2.AddRequirement("Wood", 20, true);
			}
			CustomPiece val3 = new CustomPiece(prefabName, basePrefab, val2);
			GameObject piecePrefab = val3.PiecePrefab;
			if (prefabName == "MagicStorageCore")
			{
				piecePrefab.AddComponent<StorageCore>();
			}
			else
			{
				piecePrefab.AddComponent<StorageUnit>();
			}
			ApplyMagicStorageLook(piecePrefab, prefabName == "MagicStorageCore");
			try
			{
				val3.Piece.m_icon = RenderManager.Instance.Render(piecePrefab, RenderManager.IsometricRotation);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("v1.1.2: could not render custom Hammer icon for " + prefabName + ": " + ex.Message));
			}
			PieceManager.Instance.AddPiece(val3);
			Log.LogInfo((object)string.Format("v0.1.38 ADD: {0}; table={1}; category={2}; usage={3}; valid={4}", prefabName, val2.PieceTable, val2.Category, string.Join(",", val2.Usage ?? Array.Empty<string>()), val3.IsValid()));
		}

		private static void ApplyMagicStorageLook(GameObject prefab, bool isCore)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Expected O, but got Unknown
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			Color val = (isCore ? new Color(0.12f, 0.32f, 0.46f, 1f) : new Color(0.16f, 0.23f, 0.31f, 1f));
			Color val2 = (isCore ? new Color(0.035f, 0.18f, 0.28f, 1f) : new Color(0.01f, 0.035f, 0.055f, 1f));
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren)
			{
				Material[] materials = val3.materials;
				foreach (Material val4 in materials)
				{
					if (!((Object)(object)val4 == (Object)null))
					{
						if (val4.HasProperty("_Color"))
						{
							val4.color = val;
						}
						if (val4.HasProperty("_BaseColor"))
						{
							val4.SetColor("_BaseColor", val);
						}
						if (val4.HasProperty("_EmissionColor"))
						{
							val4.EnableKeyword("_EMISSION");
							val4.SetColor("_EmissionColor", val2);
						}
					}
				}
				val3.materials = materials;
			}
			if (isCore)
			{
				GameObject val5 = new GameObject("MagicStorageCoreGlow");
				val5.transform.SetParent(prefab.transform, false);
				val5.transform.localPosition = new Vector3(0f, 0.75f, 0f);
				Light val6 = val5.AddComponent<Light>();
				val6.type = (LightType)2;
				val6.color = new Color(0.18f, 0.55f, 0.72f);
				val6.range = 2.6f;
				val6.intensity = 0.55f;
				val6.shadows = (LightShadows)0;
			}
		}
	}
	public sealed class StorageCore : MonoBehaviour
	{
		internal const string NetworkIdZdoKey = "magicstorage_network_id";

		private LineRenderer _rangeLine;

		private GameObject _fogWall;

		private ZNetView _nview;

		public Container Container => ((Component)this).GetComponent<Container>();

		public bool RangeVisible { get; private set; }

		public string NetworkId => EnsureNetworkId();

		private string EnsureNetworkId()
		{
			try
			{
				if ((Object)(object)_nview == (Object)null)
				{
					_nview = ((Component)this).GetComponent<ZNetView>();
				}
				if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
				{
					return "";
				}
				ZDO zDO = _nview.GetZDO();
				if (zDO == null)
				{
					return "";
				}
				string text = zDO.GetString("magicstorage_network_id", "");
				if (!string.IsNullOrEmpty(text))
				{
					return text;
				}
				if (!_nview.IsOwner())
				{
					AccessTools.Method(typeof(ZNetView), "ClaimOwnership", Type.EmptyTypes, (Type[])null)?.Invoke(_nview, null);
				}
				if (!_nview.IsOwner())
				{
					return "";
				}
				text = zDO.GetString("magicstorage_network_id", "");
				if (!string.IsNullOrEmpty(text))
				{
					return text;
				}
				text = Guid.NewGuid().ToString("N");
				zDO.Set("magicstorage_network_id", text);
				return text;
			}
			catch (Exception ex)
			{
				MagicStoragePlugin.Log.LogWarning((object)("v1.1.2: could not initialize Core network id: " + ex.Message));
				return "";
			}
		}

		public void ToggleRange()
		{
			RangeVisible = !RangeVisible;
			EnsureRangeRenderer();
			if ((Object)(object)_rangeLine != (Object)null)
			{
				((Renderer)_rangeLine).enabled = RangeVisible;
			}
			if ((Object)(object)_fogWall != (Object)null)
			{
				_fogWall.SetActive(RangeVisible);
			}
		}

		private void EnsureRangeRenderer()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_00b0: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Expected O, but got Unknown
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: 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_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: 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_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Expected O, but got Unknown
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Expected O, but got Unknown
			if ((Object)(object)_rangeLine != (Object)null)
			{
				return;
			}
			GameObject val = new GameObject("MagicStorageRange");
			val.transform.SetParent(((Component)this).transform, false);
			_rangeLine = val.AddComponent<LineRenderer>();
			_rangeLine.useWorldSpace = false;
			_rangeLine.loop = true;
			_rangeLine.widthMultiplier = 0.08f;
			_rangeLine.positionCount = 96;
			((Renderer)_rangeLine).material = new Material(Shader.Find("Sprites/Default"));
			_rangeLine.startColor = new Color(0.15f, 0.65f, 0.85f, 0.65f);
			_rangeLine.endColor = new Color(0.15f, 0.65f, 0.85f, 0.65f);
			float value = MagicStoragePlugin.NetworkRadius.Value;
			for (int i = 0; i < _rangeLine.positionCount; i++)
			{
				float num = (float)i * (float)Math.PI * 2f / (float)_rangeLine.positionCount;
				_rangeLine.SetPosition(i, new Vector3(Mathf.Cos(num) * value, 0.12f, Mathf.Sin(num) * value));
			}
			((Renderer)_rangeLine).enabled = RangeVisible;
			_fogWall = new GameObject("MagicStorageRangeFogWall");
			_fogWall.transform.SetParent(((Component)this).transform, false);
			MeshFilter val2 = _fogWall.AddComponent<MeshFilter>();
			MeshRenderer val3 = _fogWall.AddComponent<MeshRenderer>();
			Vector3[] array = (Vector3[])(object)new Vector3[194];
			Vector2[] array2 = (Vector2[])(object)new Vector2[array.Length];
			int[] array3 = new int[576];
			for (int j = 0; j <= 96; j++)
			{
				float num2 = (float)j / 96f;
				float num3 = num2 * (float)Math.PI * 2f;
				float num4 = Mathf.Cos(num3) * value;
				float num5 = Mathf.Sin(num3) * value;
				array[j * 2] = new Vector3(num4, 0.15f, num5);
				array[j * 2 + 1] = new Vector3(num4, 5.5f, num5);
				array2[j * 2] = new Vector2(num2, 0f);
				array2[j * 2 + 1] = new Vector2(num2, 1f);
				if (j < 96)
				{
					int num6 = j * 2;
					int num7 = j * 6;
					array3[num7] = num6;
					array3[num7 + 1] = num6 + 1;
					array3[num7 + 2] = num6 + 2;
					array3[num7 + 3] = num6 + 2;
					array3[num7 + 4] = num6 + 1;
					array3[num7 + 5] = num6 + 3;
				}
			}
			Mesh val4 = new Mesh
			{
				name = "MagicStorageRangeFogMesh",
				vertices = array,
				uv = array2,
				triangles = array3
			};
			val4.RecalculateNormals();
			val4.RecalculateBounds();
			val2.sharedMesh = val4;
			Shader val5 = Shader.Find("Sprites/Default");
			Material material = new Material(val5)
			{
				color = new Color(0.1f, 0.48f, 0.62f, 0.105f)
			};
			((Renderer)val3).material = material;
			((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val3).receiveShadows = false;
			_fogWall.SetActive(RangeVisible);
		}

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			Container container = Container;
			InventorySizer.SetSize((container != null) ? container.GetInventory() : null, 4, 4);
		}

		private void Start()
		{
			EnsureNetworkId();
		}
	}
	public sealed class StorageUnit : MonoBehaviour
	{
		private sealed class TierDef
		{
			public string Name;

			public int Width;

			public int Height;

			public Color Color;

			public Color Emission;

			public UpgradeCost[] UpgradeCosts;
		}

		private sealed class UpgradeCost
		{
			public string Prefab;

			public string Display;

			public int Amount;

			public UpgradeCost(string prefab, string display, int amount)
			{
				Prefab = prefab;
				Display = display;
				Amount = amount;
			}
		}

		internal const string TierZdoKey = "magicstorage_unit_tier";

		private static readonly TierDef[] Tiers = new TierDef[5]
		{
			new TierDef
			{
				Name = "Basic",
				Width = 4,
				Height = 4,
				Color = new Color(0.24f, 0.16f, 0.09f, 1f),
				Emission = new Color(0f, 0f, 0f, 1f),
				UpgradeCosts = Array.Empty<UpgradeCost>()
			},
			new TierDef
			{
				Name = "Bronze",
				Width = 6,
				Height = 4,
				Color = new Color(0.46f, 0.27f, 0.12f, 1f),
				Emission = new Color(0.055f, 0.026f, 0.008f, 1f),
				UpgradeCosts = new UpgradeCost[2]
				{
					new UpgradeCost("Bronze", "Bronze", 1),
					new UpgradeCost("FineWood", "Fine Wood", 10)
				}
			},
			new TierDef
			{
				Name = "Iron",
				Width = 6,
				Height = 6,
				Color = new Color(0.22f, 0.23f, 0.24f, 1f),
				Emission = new Color(0.012f, 0.015f, 0.018f, 1f),
				UpgradeCosts = new UpgradeCost[2]
				{
					new UpgradeCost("Iron", "Iron", 3),
					new UpgradeCost("ElderBark", "Ancient Bark", 10)
				}
			},
			new TierDef
			{
				Name = "Silver",
				Width = 8,
				Height = 6,
				Color = new Color(0.58f, 0.64f, 0.69f, 1f),
				Emission = new Color(0.035f, 0.055f, 0.07f, 1f),
				UpgradeCosts = new UpgradeCost[2]
				{
					new UpgradeCost("Silver", "Silver", 2),
					new UpgradeCost("Obsidian", "Obsidian", 5)
				}
			},
			new TierDef
			{
				Name = "Black Metal",
				Width = 8,
				Height = 8,
				Color = new Color(0.075f, 0.07f, 0.095f, 1f),
				Emission = new Color(0.02f, 0.018f, 0.045f, 1f),
				UpgradeCosts = new UpgradeCost[2]
				{
					new UpgradeCost("BlackMetal", "Black Metal", 5),
					new UpgradeCost("FineWood", "Fine Wood", 10)
				}
			}
		};

		private ZNetView _nview;

		private int _appliedTier = -1;

		private float _nextTierCheck;

		public Container Container => ((Component)this).GetComponent<Container>();

		public int Tier => ReadTier();

		public string TierName
		{
			get
			{
				int num = Mathf.Clamp(ReadTier(), 0, Tiers.Length - 1);
				return Tiers[num].Name;
			}
		}

		public int Capacity
		{
			get
			{
				int num = Mathf.Clamp(ReadTier(), 0, Tiers.Length - 1);
				return Tiers[num].Width * Tiers[num].Height;
			}
		}

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

		private void Start()
		{
			ApplyTier(ReadTier());
		}

		private void Update()
		{
			if (!(Time.unscaledTime < _nextTierCheck))
			{
				_nextTierCheck = Time.unscaledTime + 0.5f;
				int num = ReadTier();
				if (num != _appliedTier)
				{
					ApplyTier(num);
				}
			}
		}

		private int ReadTier()
		{
			try
			{
				if ((Object)(object)_nview == (Object)null)
				{
					_nview = ((Component)this).GetComponent<ZNetView>();
				}
				if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
				{
					return 0;
				}
				ZDO zDO = _nview.GetZDO();
				if (zDO == null)
				{
					return 0;
				}
				return Mathf.Clamp(zDO.GetInt("magicstorage_unit_tier", 0), 0, Tiers.Length - 1);
			}
			catch
			{
				return 0;
			}
		}

		private void WriteTier(int tier)
		{
			tier = Mathf.Clamp(tier, 0, Tiers.Length - 1);
			try
			{
				if ((Object)(object)_nview == (Object)null)
				{
					_nview = ((Component)this).GetComponent<ZNetView>();
				}
				if (!((Object)(object)_nview == (Object)null) && _nview.IsValid())
				{
					if (!_nview.IsOwner())
					{
						AccessTools.Method(typeof(ZNetView), "ClaimOwnership", Type.EmptyTypes, (Type[])null)?.Invoke(_nview, null);
					}
					ZDO zDO = _nview.GetZDO();
					if (zDO != null)
					{
						zDO.Set("magicstorage_unit_tier", tier);
					}
				}
			}
			catch (Exception ex)
			{
				MagicStoragePlugin.Log.LogWarning((object)("v1.1.2: failed saving Storage Unit tier: " + ex.Message));
			}
		}

		private void ApplyTier(int tier)
		{
			//IL_0041: 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)
			tier = Mathf.Clamp(tier, 0, Tiers.Length - 1);
			TierDef tierDef = Tiers[tier];
			Container container = Container;
			InventorySizer.SetSize((container != null) ? container.GetInventory() : null, tierDef.Width, tierDef.Height);
			ApplyTierColor(tierDef.Color, tierDef.Emission);
			_appliedTier = tier;
			MagicStoragePlugin.Log.LogInfo((object)$"v0.1.38 Storage Unit tier applied: {tierDef.Name} ({tierDef.Width}x{tierDef.Height} = {tierDef.Width * tierDef.Height} slots).");
		}

		private void ApplyTierColor(Color color, Color emission)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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)
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Material[] materials = val.materials;
				foreach (Material val2 in materials)
				{
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					if (val2.HasProperty("_Color"))
					{
						val2.color = color;
					}
					if (val2.HasProperty("_BaseColor"))
					{
						val2.SetColor("_BaseColor", color);
					}
					if (val2.HasProperty("_EmissionColor"))
					{
						if (((Color)(ref emission)).maxColorComponent > 0.001f)
						{
							val2.EnableKeyword("_EMISSION");
							val2.SetColor("_EmissionColor", emission);
						}
						else
						{
							val2.SetColor("_EmissionColor", Color.black);
						}
					}
				}
				val.materials = materials;
			}
		}

		internal bool TryUpgrade(Humanoid user)
		{
			if ((Object)(object)user == (Object)null || (Object)(object)user != (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			int num = ReadTier();
			if (num >= Tiers.Length - 1)
			{
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)1, $"Storage Unit is already maximum tier: {Tiers[num].Name} ({Capacity} slots)", 0, (Sprite)null, false, true);
				}
				return true;
			}
			int num2 = num + 1;
			TierDef tierDef = Tiers[num2];
			Player localPlayer = Player.m_localPlayer;
			Inventory val = ((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null);
			if (val == null)
			{
				return true;
			}
			List<string> list = new List<string>();
			UpgradeCost[] upgradeCosts = tierDef.UpgradeCosts;
			foreach (UpgradeCost upgradeCost in upgradeCosts)
			{
				int num3 = CountPrefab(val, upgradeCost.Prefab);
				if (num3 < upgradeCost.Amount)
				{
					list.Add($"{upgradeCost.Display} {num3}/{upgradeCost.Amount}");
				}
			}
			if (list.Count > 0)
			{
				MessageHud instance2 = MessageHud.instance;
				if (instance2 != null)
				{
					instance2.ShowMessage((MessageType)1, "Upgrade to " + tierDef.Name + " needs: " + string.Join(", ", list), 0, (Sprite)null, false, true);
				}
				return true;
			}
			UpgradeCost[] upgradeCosts2 = tierDef.UpgradeCosts;
			foreach (UpgradeCost upgradeCost2 in upgradeCosts2)
			{
				ConsumePrefab(val, upgradeCost2.Prefab, upgradeCost2.Amount);
			}
			WriteTier(num2);
			ApplyTier(num2);
			MessageHud instance3 = MessageHud.instance;
			if (instance3 != null)
			{
				instance3.ShowMessage((MessageType)1, $"Storage Unit upgraded to {tierDef.Name}: {tierDef.Width * tierDef.Height} slots", 0, (Sprite)null, false, true);
			}
			MagicStoragePlugin.Log.LogInfo((object)$"v0.1.38 Storage Unit upgraded: {Tiers[num].Name} -> {tierDef.Name}; capacity {tierDef.Width * tierDef.Height}.");
			return true;
		}

		internal string BuildHoverText()
		{
			int num = Mathf.Clamp(ReadTier(), 0, Tiers.Length - 1);
			TierDef tierDef = Tiers[num];
			if (num >= Tiers.Length - 1)
			{
				return $"Storage Unit — {tierDef.Name}\n{tierDef.Width * tierDef.Height} slots\nMaximum storage tier";
			}
			TierDef tierDef2 = Tiers[num + 1];
			string text = string.Join(" + ", tierDef2.UpgradeCosts.Select((UpgradeCost c) => $"{c.Amount} {c.Display}"));
			string text2 = $"Storage Unit — {tierDef.Name}\n{tierDef.Width * tierDef.Height} slots\n[<color=yellow><b>$KEY_Use</b></color>] Upgrade to {tierDef2.Name}\n{text}";
			return (Localization.instance != null) ? Localization.instance.Localize(text2) : text2;
		}

		private static int CountPrefab(Inventory inventory, string prefabName)
		{
			if (inventory == null || string.IsNullOrEmpty(prefabName))
			{
				return 0;
			}
			int num = 0;
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem != null && !((Object)(object)allItem.m_dropPrefab == (Object)null))
				{
					string a = ((Object)allItem.m_dropPrefab).name.Replace("(Clone)", "");
					if (string.Equals(a, prefabName, StringComparison.Ordinal))
					{
						num += allItem.m_stack;
					}
				}
			}
			return num;
		}

		private static bool ConsumePrefab(Inventory inventory, string prefabName, int amount)
		{
			if (inventory == null || amount <= 0)
			{
				return true;
			}
			int num = amount;
			foreach (ItemData item in inventory.GetAllItems().ToList())
			{
				if (num <= 0)
				{
					break;
				}
				if (item != null && !((Object)(object)item.m_dropPrefab == (Object)null))
				{
					string a = ((Object)item.m_dropPrefab).name.Replace("(Clone)", "");
					if (string.Equals(a, prefabName, StringComparison.Ordinal))
					{
						int num2 = Math.Min(num, item.m_stack);
						inventory.RemoveItem(item, num2);
						num -= num2;
					}
				}
			}
			return num <= 0;
		}
	}
	[HarmonyPatch]
	internal static class StorageCoreInteractPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in typeof(Container).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "Interact" && m.ReturnType == typeof(bool) && m.GetParameters().Any((ParameterInfo p) => typeof(Humanoid).IsAssignableFrom(p.ParameterType))
				select m;
		}

		private static bool Prefix(Container __instance, ref bool __result)
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)((Component)__instance).GetComponent<StorageCore>() == (Object)null)
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch]
	internal static class StorageCoreHoverPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in typeof(Container).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "GetHoverText" && m.ReturnType == typeof(string) && m.GetParameters().Length == 0
				select m;
		}

		private static void Postfix(Container __instance, ref string __result)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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)
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).GetComponent<StorageCore>() == (Object)null))
			{
				object obj;
				if (MagicStoragePlugin.OpenKey == null)
				{
					obj = "G";
				}
				else
				{
					KeyboardShortcut value = MagicStoragePlugin.OpenKey.Value;
					obj = ((object)((KeyboardShortcut)(ref value)).MainKey/*cast due to .constrained prefix*/).ToString();
				}
				string text = (string)obj;
				__result = "Storage Core\n[" + text + "] Open Magic Storage";
			}
		}
	}
	[HarmonyPatch]
	internal static class StorageUnitInteractPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in typeof(Container).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "Interact" && m.ReturnType == typeof(bool) && m.GetParameters().Any((ParameterInfo p) => typeof(Humanoid).IsAssignableFrom(p.ParameterType))
				select m;
		}

		private static bool Prefix(Container __instance, MethodBase __originalMethod, object[] __args, ref bool __result)
		{
			StorageUnit storageUnit = ((__instance != null) ? ((Component)__instance).GetComponent<StorageUnit>() : null);
			if ((Object)(object)storageUnit == (Object)null)
			{
				return true;
			}
			Humanoid val = __args?.OfType<Humanoid>().FirstOrDefault();
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			bool flag = false;
			ParameterInfo[] array = __originalMethod?.GetParameters();
			if (array != null && __args != null)
			{
				bool flag2 = default(bool);
				for (int i = 0; i < array.Length && i < __args.Length; i++)
				{
					if (array[i].ParameterType == typeof(bool) && string.Equals(array[i].Name, "hold", StringComparison.OrdinalIgnoreCase))
					{
						object obj = __args[i];
						int num;
						if (obj is bool)
						{
							flag2 = (bool)obj;
							num = 1;
						}
						else
						{
							num = 0;
						}
						flag = (byte)((uint)num & (flag2 ? 1u : 0u)) != 0;
						break;
					}
				}
			}
			if (flag)
			{
				__result = false;
				return false;
			}
			if ((Object)(object)val == (Object)(object)Player.m_localPlayer)
			{
				__result = storageUnit.TryUpgrade(val);
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class StorageUnitHoverPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in typeof(Container).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "GetHoverText" && m.ReturnType == typeof(string) && m.GetParameters().Length == 0
				select m;
		}

		private static void Postfix(Container __instance, ref string __result)
		{
			StorageUnit storageUnit = ((__instance != null) ? ((Component)__instance).GetComponent<StorageUnit>() : null);
			if ((Object)(object)storageUnit != (Object)null)
			{
				__result = storageUnit.BuildHoverText();
			}
		}
	}
	internal static class InventorySizer
	{
		public static void SetSize(Inventory inventory, int width, int height)
		{
			if (inventory == null)
			{
				return;
			}
			try
			{
				MethodInfo method = typeof(Inventory).GetMethod("SetSize", new Type[2]
				{
					typeof(int),
					typeof(int)
				});
				if (method != null)
				{
					method.Invoke(inventory, new object[2] { width, height });
				}
				else
				{
					FieldInfo field = typeof(Inventory).GetField("m_width", BindingFlags.Instance | BindingFlags.NonPublic);
					FieldInfo field2 = typeof(Inventory).GetField("m_height", BindingFlags.Instance | BindingFlags.NonPublic);
					field?.SetValue(inventory, width);
					field2?.SetValue(inventory, height);
				}
			}
			catch (Exception ex)
			{
				MagicStoragePlugin.Log.LogWarning((object)("Could not resize storage inventory: " + ex.Message));
			}
		}
	}
	public static class StorageNetwork
	{
		private static bool EnsureWriteOwnership(Container container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return false;
			}
			try
			{
				ZNetView component = ((Component)container).GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null || !component.IsValid())
				{
					return true;
				}
				if (!component.IsOwner())
				{
					AccessTools.Method(typeof(ZNetView), "ClaimOwnership", Type.EmptyTypes, (Type[])null)?.Invoke(component, null);
				}
				return component.IsOwner();
			}
			catch (Exception ex)
			{
				MagicStoragePlugin.Log.LogWarning((object)("Storage sync: could not claim Container ownership: " + ex.Message));
				return false;
			}
		}

		private static void ReloadFromNetwork(Container container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return;
			}
			try
			{
				ZNetView component = ((Component)container).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid() && !component.IsOwner())
				{
					AccessTools.Method(typeof(Container), "Load", Type.EmptyTypes, (Type[])null)?.Invoke(container, null);
				}
			}
			catch (Exception ex)
			{
				MagicStoragePlugin.Log.LogWarning((object)("Storage sync: Container reload failed: " + ex.Message));
			}
		}

		private static void SaveToNetwork(Container container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return;
			}
			try
			{
				if (EnsureWriteOwnership(container))
				{
					AccessTools.Method(typeof(Container), "Save", Type.EmptyTypes, (Type[])null)?.Invoke(container, null);
				}
			}
			catch (Exception ex)
			{
				MagicStoragePlugin.Log.LogWarning((object)("Storage sync: Container save failed: " + ex.Message));
			}
		}

		public static void RefreshNetworkState(IEnumerable<Container> containers)
		{
			if (containers == null)
			{
				return;
			}
			foreach (Container container in containers)
			{
				ReloadFromNetwork(container);
			}
		}

		public static List<Container> FindUnits(StorageCore core)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			List<Container> list = new List<Container>();
			if ((Object)(object)core == (Object)null)
			{
				return list;
			}
			StorageUnit[] array = Object.FindObjectsByType<StorageUnit>((FindObjectsSortMode)0);
			foreach (StorageUnit storageUnit in array)
			{
				if (!((Object)(object)storageUnit == (Object)null) && !((Object)(object)storageUnit.Container == (Object)null) && Vector3.Distance(((Component)core).transform.position, ((Component)storageUnit).transform.position) <= MagicStoragePlugin.NetworkRadius.Value)
				{
					list.Add(storageUnit.Container);
				}
			}
			if ((Object)(object)core.Container != (Object)null)
			{
				list.Insert(0, core.Container);
			}
			RefreshNetworkState(list);
			return list;
		}

		public static IEnumerable<ItemData> AllItems(StorageCore core)
		{
			foreach (Container container in FindUnits(core))
			{
				foreach (ItemData item in container.GetInventory().GetAllItems())
				{
					if (item != null)
					{
						yield return item;
					}
				}
			}
		}

		public static int Count(StorageCore core, string name)
		{
			return (from x in AllItems(core)
				where x.m_shared != null && x.m_shared.m_name == name
				select x).Sum((ItemData x) => x.m_stack);
		}

		private static bool TryRepairOnDeposit(ItemData item, Player player, out string reason)
		{
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			reason = null;
			if (!MagicStoragePlugin.RepairOnDeposit.Value || item?.m_shared == null || (Object)(object)player == (Object)null)
			{
				return false;
			}
			if (item.m_durability >= item.GetMaxDurability())
			{
				return false;
			}
			try
			{
				Recipe val = null;
				if ((Object)(object)ObjectDB.instance != (Object)null)
				{
					val = ((IEnumerable<Recipe>)ObjectDB.instance.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => (Object)(object)r != (Object)null && (Object)(object)r.m_item != (Object)null && r.m_item.m_itemData?.m_shared != null && r.m_item.m_itemData.m_shared.m_name == item.m_shared.m_name));
				}
				if ((Object)(object)val == (Object)null)
				{
					reason = "No repair recipe";
					return false;
				}
				CraftingStation craftingStation = val.m_craftingStation;
				int num = Math.Max(1, val.m_minStationLevel);
				if ((Object)(object)craftingStation == (Object)null)
				{
					item.m_durability = item.GetMaxDurability();
					reason = "Repaired";
					return true;
				}
				string b = ((Object)((Component)craftingStation).gameObject).name.Replace("(Clone)", "");
				CraftingStation val2 = null;
				int num2 = 0;
				CraftingStation[] array = Object.FindObjectsByType<CraftingStation>((FindObjectsSortMode)0);
				foreach (CraftingStation val3 in array)
				{
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					string a = ((Object)((Component)val3).gameObject).name.Replace("(Clone)", "");
					if (!string.Equals(a, b, StringComparison.OrdinalIgnoreCase) || Vector3.Distance(((Component)player).transform.position, ((Component)val3).transform.position) > 20f)
					{
						continue;
					}
					int num4 = 1;
					try
					{
						MethodInfo methodInfo = AccessTools.Method(typeof(CraftingStation), "GetLevel", (Type[])null, (Type[])null);
						if (methodInfo != null)
						{
							num4 = Convert.ToInt32(methodInfo.Invoke(val3, null));
						}
					}
					catch
					{
					}
					if (num4 > num2)
					{
						val2 = val3;
						num2 = num4;
					}
				}
				string arg = ((Localization.instance != null) ? Localization.instance.Localize(craftingStation.m_name) : craftingStation.m_name);
				if ((Object)(object)val2 == (Object)null)
				{
					reason = $"Requires {arg} level {num}";
					return false;
				}
				if (num2 < num)
				{
					reason = $"Requires {arg} level {num} (nearby: {num2})";
					return false;
				}
				item.m_durability = item.GetMaxDurability();
				reason = $"Repaired at {arg} level {num2}";
				return true;
			}
			catch (Exception ex)
			{
				MagicStoragePlugin.Log.LogWarning((object)("Repair-on-deposit check failed for " + item.m_shared.m_name + ": " + ex.Message));
				reason = "Repair check failed";
				return false;
			}
		}

		public static int DepositAll(StorageCore core, Inventory playerInventory)
		{
			if ((Object)(object)core == (Object)null || playerInventory == null)
			{
				return 0;
			}
			int num = 0;
			int num2 = 0;
			Player localPlayer = Player.m_localPlayer;
			List<Container> list = FindUnits(core);
			foreach (ItemData item in playerInventory.GetAllItems().ToList())
			{
				if (item == null || item.m_equipped || item.m_shared == null)
				{
					continue;
				}
				int stack = item.m_stack;
				if (TryRepairOnDeposit(item, localPlayer, out var _))
				{
					num2++;
				}
				foreach (Container item2 in list)
				{
					if (item.m_stack <= 0)
					{
						break;
					}
					if (EnsureWriteOwnership(item2))
					{
						Inventory inventory = item2.GetInventory();
						ItemData val = item.Clone();
						if (inventory.AddItem(val))
						{
							playerInventory.RemoveItem(item, item.m_stack);
							num += stack;
							SaveToNetwork(item2);
							break;
						}
					}
				}
			}
			if (num2 > 0)
			{
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)1, $"Repaired {num2} deposited item(s)", 0, (Sprite)null, false, true);
				}
			}
			return num;
		}

		public static int StoredCount(StorageCore core, string itemName)
		{
			return Count(core, itemName);
		}

		public static bool Consume(StorageCore core, string itemName, int amount)
		{
			int num = amount;
			foreach (Container item in FindUnits(core))
			{
				foreach (ItemData item2 in (from x in item.GetInventory().GetAllItems()
					where x?.m_shared?.m_name == itemName
					select x).ToList())
				{
					int num2 = Math.Min(num, item2.m_stack);
					if (EnsureWriteOwnership(item))
					{
						item.GetInventory().RemoveItem(item2, num2);
						SaveToNetwork(item);
						num -= num2;
						if (num <= 0)
						{
							return true;
						}
					}
				}
			}
			return num <= 0;
		}

		public static bool DepositItem(StorageCore core, ItemData item, Inventory source)
		{
			if ((Object)(object)core == (Object)null || item == null || source == null || item.m_equipped)
			{
				return false;
			}
			TryRepairOnDeposit(item, Player.m_localPlayer, out var _);
			foreach (Container item2 in FindUnits(core))
			{
				if (EnsureWriteOwnership(item2))
				{
					ItemData val = item.Clone();
					if (item2.GetInventory().AddItem(val))
					{
						source.RemoveItem(item, item.m_stack);
						SaveToNetwork(item2);
						return true;
					}
				}
			}
			return false;
		}

		public static bool TryGetDragSource(StorageCore core, string itemName, out ItemData item, out Inventory inventory)
		{
			item = null;
			inventory = null;
			if ((Object)(object)core == (Object)null)
			{
				return false;
			}
			foreach (Container item2 in FindUnits(core))
			{
				Inventory val = ((item2 != null) ? item2.GetInventory() : null);
				if (val != null)
				{
					ItemData val2 = ((IEnumerable<ItemData>)val.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData x) => x != null && x.m_shared != null && x.m_shared.m_name == itemName));
					if (val2 != null)
					{
						item = val2;
						inventory = val;
						return true;
					}
				}
			}
			return false;
		}

		public static bool WithdrawOne(StorageCore core, string itemName, Inventory destination)
		{
			if ((Object)(object)core == (Object)null || destination == null)
			{
				return false;
			}
			foreach (Container item in FindUnits(core))
			{
				ItemData val = ((IEnumerable<ItemData>)item.GetInventory().GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData x) => x != null && x.m_shared != null && x.m_shared.m_name == itemName));
				if (val == null)
				{
					continue;
				}
				if (!EnsureWriteOwnership(item))
				{
					return false;
				}
				ItemData val2 = val.Clone();
				val2.m_stack = 1;
				if (!destination.CanAddItem(val2, -1))
				{
					return false;
				}
				if (!destination.AddItem(val2))
				{
					return false;
				}
				item.GetInventory().RemoveItem(val, 1);
				SaveToNetwork(item);
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Hud), "UpdateCrosshair")]
	internal static class HideVanillaHoverWhileStorageOpenPatch
	{
		private static void Postfix(Hud __instance)
		{
			if (!StorageGui.IsOpen || (Object)(object)__instance == (Object)null)
			{
				return;
			}
			try
			{
				object obj = AccessTools.Field(typeof(Hud), "m_hoverName")?.GetValue(__instance);
				(obj?.GetType().GetProperty("text"))?.SetValue(obj, string.Empty, null);
			}
			catch
			{
			}
		}
	}
	internal static class WirelessRemoteSystem
	{
		private sealed class TierInfo
		{
			public string Name;

			public float Range;

			public string TrophyPrefab;

			public string TrophyName;
		}

		internal const string RemotePrefabName = "MagicStorageWirelessRemote";

		private const string CoreIdKey = "magicstorage.remote.core";

		private const string CorePosKey = "magicstorage.remote.corepos";

		private const string TierKey = "magicstorage.remote.tier";

		private static readonly TierInfo[] Tiers = new TierInfo[8]
		{
			new TierInfo
			{
				Name = "Base",
				Range = 50f,
				TrophyPrefab = null,
				TrophyName = null
			},
			new TierInfo
			{
				Name = "Eikthyr",
				Range = 100f,
				TrophyPrefab = "TrophyEikthyr",
				TrophyName = "Eikthyr Trophy"
			},
			new TierInfo
			{
				Name = "The Elder",
				Range = 200f,
				TrophyPrefab = "TrophyTheElder",
				TrophyName = "The Elder Trophy"
			},
			new TierInfo
			{
				Name = "Bonemass",
				Range = 400f,
				TrophyPrefab = "TrophyBonemass",
				TrophyName = "Bonemass Trophy"
			},
			new TierInfo
			{
				Name = "Moder",
				Range = 800f,
				TrophyPrefab = "TrophyDragonQueen",
				TrophyName = "Moder Trophy"
			},
			new TierInfo
			{
				Name = "Yagluth",
				Range = 1600f,
				TrophyPrefab = "TrophyGoblinKing",
				TrophyName = "Yagluth Trophy"
			},
			new TierInfo
			{
				Name = "The Queen",
				Range = 3200f,
				TrophyPrefab = "TrophySeekerQueen",
				TrophyName = "The Queen Trophy"
			},
			new TierInfo
			{
				Name = "Fader",
				Range = float.PositiveInfinity,
				TrophyPrefab = "TrophyFader",
				TrophyName = "Fader Trophy"
			}
		};

		private static bool _handlingUse;

		internal static bool IsRemote(ItemData item)
		{
			if ((Object)(object)item?.m_dropPrefab == (Object)null)
			{
				return false;
			}
			string a = ((Object)item.m_dropPrefab).name.Replace("(Clone)", "");
			return string.Equals(a, "MagicStorageWirelessRemote", StringComparison.Ordinal);
		}

		private static int GetTier(ItemData item)
		{
			if (item?.m_customData == null)
			{
				return 0;
			}
			if (item.m_customData.TryGetValue("magicstorage.remote.tier", out var value) && int.TryParse(value, out var result))
			{
				return Mathf.Clamp(result, 0, Tiers.Length - 1);
			}
			return 0;
		}

		private static void SetTier(ItemData item, int tier)
		{
			if (item != null)
			{
				if (item.m_customData == null)
				{
					item.m_customData = new Dictionary<string, string>();
				}
				item.m_customData["magicstorage.remote.tier"] = Mathf.Clamp(tier, 0, Tiers.Length - 1).ToString(CultureInfo.InvariantCulture);
			}
		}

		internal static bool IsLinked(ItemData item)
		{
			return IsRemote(item) && !string.IsNullOrEmpty(GetCoreId(item));
		}

		internal static void OpenLinkedFromKey(ItemData item)
		{
			if (IsLinked(item))
			{
				TryOpenLinked(item);
			}
		}

		private static string GetCoreId(ItemData item)
		{
			if (item?.m_customData != null && item.m_customData.TryGetValue("magicstorage.remote.core", out var value))
			{
				return value ?? "";
			}
			return "";
		}

		private static bool TryGetCorePosition(ItemData item, out Vector3 position)
		{
			//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_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)
			position = Vector3.zero;
			if (item?.m_customData == null || !item.m_customData.TryGetValue("magicstorage.remote.corepos", out var value) || string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			string[] array = value.Split(new char[1] { ',' });
			if (array.Length != 3)
			{
				return false;
			}
			if (!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 void SetLink(ItemData item, StorageCore core)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			if (item == null || (Object)(object)core == (Object)null)
			{
				return;
			}
			string networkId = core.NetworkId;
			if (string.IsNullOrEmpty(networkId))
			{
				Message("Could not create a persistent link to that Core.");
				return;
			}
			if (item.m_customData == null)
			{
				item.m_customData = new Dictionary<string, string>();
			}
			item.m_customData["magicstorage.remote.core"] = networkId;
			Vector3 position = ((Component)core).transform.position;
			item.m_customData["magicstorage.remote.corepos"] = position.x.ToString("R", CultureInfo.InvariantCulture) + "," + position.y.ToString("R", CultureInfo.InvariantCulture) + "," + position.z.ToString("R", CultureInfo.InvariantCulture);
			Message("Wireless Storage Remote linked. Range: " + RangeText(GetTier(item)));
			MagicStoragePlugin.Log.LogInfo((object)$"v0.1.38 remote: linked to Core network {networkId} at {position}.");
		}

		internal static bool HandleUse(ItemData item)
		{
			if (!IsRemote(item) || _handlingUse)
			{
				return false;
			}
			_handlingUse = true;
			try
			{
				bool flag = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
				if (Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305))
				{
					TryUpgrade(item);
					return true;
				}
				if (flag)
				{
					StorageCore storageCore = LookedAtCore();
					if ((Object)(object)storageCore == (Object)null)
					{
						Message("Look at a Storage Core, then Shift + Use the remote to link it.");
					}
					else
					{
						SetLink(item, storageCore);
					}
					return true;
				}
				string coreId = GetCoreId(item);
				if (string.IsNullOrEmpty(coreId))
				{
					StorageCore storageCore2 = LookedAtCore();
					if ((Object)(object)storageCore2 != (Object)null)
					{
						SetLink(item, storageCore2);
					}
					else
					{
						Message("Remote is unlinked. Look at a Storage Core and use it once, or Shift + Use to link.");
					}
					return true;
				}
				TryOpenLinked(item);
				return true;
			}
			finally
			{
				_handlingUse = false;
			}
		}

		private static void TryUpgrade(ItemData item)
		{
			int tier = GetTier(item);
			if (tier >= Tiers.Length - 1)
			{
				Message("Wireless Storage Remote is already at Fader tier: unlimited range.");
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			Inventory val = ((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null);
			if (val != null)
			{
				TierInfo next = Tiers[tier + 1];
				ItemData val2 = ((IEnumerable<ItemData>)val.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData x) => (Object)(object)x?.m_dropPrefab != (Object)null && string.Equals(((Object)x.m_dropPrefab).name.Replace("(Clone)", ""), next.TrophyPrefab, StringComparison.Ordinal)));
				if (val2 == null)
				{
					Message("Next wireless upgrade requires: " + next.TrophyName);
					return;
				}
				val.RemoveItem(val2, 1);
				SetTier(item, tier + 1);
				Message("Wireless range upgraded: " + next.Name + " — " + RangeText(tier + 1));
				MagicStoragePlugin.Log.LogInfo((object)$"v0.1.38 remote: upgraded to tier {tier + 1} ({next.Name}, {RangeText(tier + 1)}).");
			}
		}

		private static void TryOpenLinked(ItemData item)
		{
			//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_00e6: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			string coreId = GetCoreId(item);
			if (!TryGetCorePosition(item, out var position))
			{
				Message("Remote link is missing its Core position. Relink it with Shift + Use.");
				return;
			}
			int tier = GetTier(item);
			float range = Tiers[tier].Range;
			float num = Vector3.Distance(((Component)localPlayer).transform.position, position);
			if (!float.IsPositiveInfinity(range) && num > range)
			{
				Message($"Linked Core is {num:0}m away. Current remote range: {range:0}m.");
				return;
			}
			StorageCore storageCore = FindLoadedCore(coreId);
			if ((Object)(object)storageCore != (Object)null)
			{
				MagicStoragePlugin.Instance?.OpenStorageCore(storageCore);
			}
			else if ((Object)(object)MagicStoragePlugin.Instance != (Object)null)
			{
				((MonoBehaviour)MagicStoragePlugin.Instance).StartCoroutine(LoadNetworkAndOpen(coreId, position, tier));
			}
		}

		private static IEnumerator LoadNetworkAndOpen(string coreId, Vector3 corePos, int tier)
		{
			//IL_000e: 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)
			if (!PokeNetworkZones(corePos))
			{
				Message("Linked Core is outside the loaded world and its zone could not be activated.");
				yield break;
			}
			for (int i = 0; i < 50; i++)
			{
				yield return (object)new WaitForSecondsRealtime(0.1f);
				StorageCore core = FindLoadedCore(coreId);
				if ((Object)(object)core != (Object)null)
				{
					MagicStoragePlugin.Log.LogInfo((object)("v0.1.38 remote: activated linked Core zone and opened tier " + Tiers[tier].Name + " remote."));
					MagicStoragePlugin.Instance?.OpenStorageCore(core);
					yield break;
				}
			}
			Message("Linked Core could not be loaded. On a dedicated server this may require server-side remote-zone support.");
		}

		private static bool PokeNetworkZones(Vector3 center)
		{
			//IL_00d7: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ZoneSystem instance = ZoneSystem.instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				MethodInfo methodInfo = typeof(ZoneSystem).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "GetZone" && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(Vector3));
				if (methodInfo == null)
				{
					return false;
				}
				MethodInfo methodInfo2 = null;
				HashSet<string> hashSet = new HashSet<string>();
				float num = Math.Max(8f, MagicStoragePlugin.NetworkRadius.Value);
				float[] array = new float[3]
				{
					0f - num,
					0f,
					num
				};
				foreach (float num3 in array)
				{
					float[] array2 = new float[3]
					{
						0f - num,
						0f,
						num
					};
					foreach (float num5 in array2)
					{
						object obj = methodInfo.Invoke(null, new object[1] { center + new Vector3(num3, 0f, num5) });
						if (obj == null)
						{
							continue;
						}
						string item = obj.ToString();
						if (!hashSet.Add(item))
						{
							continue;
						}
						if (methodInfo2 == null)
						{
							Type zoneType = obj.GetType();
							methodInfo2 = typeof(ZoneSystem).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "PokeLocalZone" && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == zoneType);
						}
						if (methodInfo2 == null)
						{
							return false;
						}
						methodInfo2.Invoke(instance, new object[1] { obj });
					}
				}
				return hashSet.Count > 0;
			}
			catch (Exception ex)
			{
				MagicStoragePlugin.Log.LogWarning((object)("v0.1.38 remote zone activation failed: " + ex.GetBaseException().Message));
				return false;
			}
		}

		private static StorageCore FindLoadedCore(string coreId)
		{
			if (string.IsNullOrEmpty(coreId))
			{
				return null;
			}
			StorageCore[] array = Object.FindObjectsByType<StorageCore>((FindObjectsSortMode)0);
			foreach (StorageCore storageCore in array)
			{
				if ((Object)(object)storageCore != (Object)null && string.Equals(storageCore.NetworkId, coreId, StringComparison.Ordinal))
				{
					return storageCore;
				}
			}
			return null;
		}

		private static StorageCore LookedAtCore()
		{
			//IL_001a: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return null;
			}
			Ray val = default(Ray);
			((Ray)(ref val))..ctor(((Character)localPlayer).GetEyePoint(), ((Character)localPlayer).GetLookDir());
			RaycastHit val2 = default(RaycastHit);
			if (!Physics.Raycast(val, ref val2, 5f))
			{
				return null;
			}
			return ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<StorageCore>();
		}

		internal static string AppendTooltip(ItemData item, string tooltip)
		{
			if (!IsRemote(item))
			{
				return tooltip;
			}
			int tier = GetTier(item);
			string text = (string.IsNullOrEmpty(GetCoreId(item)) ? "Unlinked" : "Linked");
			List<string> list = new List<string>
			{
				"",
				"<color=#75d7ff>Wireless Tier:</color> " + Tiers[tier].Name,
				"<color=#75d7ff>Range:</color> " + RangeText(tier),
				"<color=#75d7ff>Core:</color> " + text,
				"Use: open linked storage",
				"Shift + Use: link/relink to looked-at Core",
				"Ctrl + Use: apply next boss trophy"
			};
			if (tier < Tiers.Length - 1)
			{
				list.Add("Next: " + Tiers[tier + 1].TrophyName + " → " + RangeText(tier + 1));
			}
			else
			{
				list.Add("Maximum tier: global/unlimited range");
			}
			string text2 = string.Join("\n", list);
			if (!string.IsNullOrEmpty(tooltip) && tooltip.Contains("<color=#75d7ff>Wireless Tier:</color>"))
			{
				return tooltip;
			}
			return tooltip + text2;
		}

		private static string RangeText(int tier)
		{
			float range = Tiers[Mathf.Clamp(tier, 0, Tiers.Length - 1)].Range;
			return float.IsPositiveInfinity(range) ? "Unlimited" : $"{range:0} m";
		}

		private static void Message(string text)
		{
			MessageHud instance = MessageHud.instance;
			if (instance != null)
			{
				instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false, true);
			}
		}
	}
	[HarmonyPatch]
	internal static class WirelessRemoteUsePatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in typeof(Humanoid).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "UseItem" && m.GetParameters().Any((ParameterInfo p) => p.ParameterType == typeof(ItemData))
				select m;
		}

		private static bool Prefix(Humanoid __instance, object[] __args)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || __args == null)
			{
				return true;
			}
			ItemData item = __args.OfType<ItemData>().FirstOrDefault();
			if (!WirelessRemoteSystem.IsRemote(item))
			{
				return true;
			}
			WirelessRemoteSystem.HandleUse(item);
			return false;
		}
	}
	[HarmonyPatch]
	internal static class WirelessRemoteTooltipPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in typeof(ItemData).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "GetTooltip" && m.ReturnType == typeof(string) && m.GetParameters().Any((ParameterInfo p) => p.ParameterType == typeof(ItemData))
				select m;
		}

		private static void Postfix(object[] __args, ref string __result)
		{
			if (__args != null)
			{
				ItemData val = __args.OfType<ItemData>().FirstOrDefault();
				if (val != null)
				{
					__result = WirelessRemoteSystem.AppendTooltip(val, __result);
				}
			}
		}
	}
	public sealed class StorageGui : MonoBehaviour
	{
		private sealed class ItemSummary
		{
			public string Name;

			public string DisplayName;

			public int Count;

			public Sprite Icon;

			public ItemData Sample;
		}

		private bool _open;

		private StorageCore _core;

		private string _search = "";

		private Vector2 _scroll;

		private Rect _window = new Rect(8f, 360f, 860f, 600f);

		private const float DesignWidth = 860f;

		private const float DesignHeight = 600f;

		private const float MinWindowWidth = 645f;

		private const float MinWindowHeight = 450f;

		private bool _layoutLoaded;

		private bool _resizing;

		private bool _movingWindow;

		private Vector2 _moveStartMouse;

		private Vector2 _moveStartPosition;

		private Vector2 _resizeStartMouse;

		private Vector2 _resizeStartSize;

		private GUIStyle _title;

		private GUIStyle _button;

		private ItemSummary _hoveredItem;

		private bool _craftingTab;

		private Vector2 _craftScroll;

		private bool _storageDragActive;

		private string _storageDragName;

		private string _storageDragDisplayName;

		private Sprite _storageDragIcon;

		private int _storageDragCount;

		private bool _storageDragWholeStack;

		private Vector2 _storageDragStartScreen;

		private readonly List<Recipe> _cachedRecipes = new List<Recipe>();

		private readonly Dictionary<string, int> _storedCounts = new Dictionary<string, int>();

		private readonly Dictionary<string, int> _stationLevels = new Dictionary<string, int>();

		private readonly List<string> _stationFilters = new List<string>();

		private string _stationFilter = "All";

		private bool _recipesCached;

		private GUIStyle _panelStyle;

		private GUIStyle _slotStyle;

		private GUIStyle _tabStyle;

		private GUIStyle _tabActiveStyle;

		private Texture2D _panelTexture;

		private Texture2D _buttonTexture;

		private Texture2D _buttonActiveTexture;

		private readonly List<Container> _cachedContainers = new List<Container>();

		private readonly List<ItemSummary> _cachedItems = new List<ItemSummary>();

		private float _nextRefresh;

		private const float RefreshInterval = 1f;

		private bool _openedPlayerInventory;

		internal static bool IsOpen { get; private set; }

		private void Update()
		{
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_005d: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			KeyboardShortcut value;
			if (_open)
			{
				if (_storageDragActive && Input.GetMouseButtonUp(0))
				{
					Vector2 val = default(Vector2);
					((Vector2)(ref val))..ctor(Input.mousePosition.x, (float)Screen.height - Input.mousePosition.y);
					float num = Vector2.Distance(val, _storageDragStartScreen);
					bool flag = !((Rect)(ref _window)).Contains(val);
					if (num < 8f || flag)
					{
						FinishStorageDragToPlayer();
					}
					ClearStorageDrag();
				}
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
				if (Time.unscaledTime >= _nextRefresh)
				{
					RefreshCache();
				}
				if (!Input.GetKeyDown((KeyCode)27))
				{
					value = MagicStoragePlugin.OpenKey.Value;
					if (!((KeyboardShortcut)(ref value)).IsDown())
					{
						return;
					}
				}
				Close();
			}
			else if (!Console.IsVisible() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()))
			{
				value = MagicStoragePlugin.OpenKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					TryOpen();
				}
			}
		}

		private void TryOpen()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			Inventory inventory = ((Humanoid)localPlayer).GetInventory();
			ItemData val = ((inventory != null) ? ((IEnumerable<ItemData>)inventory.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData x) => WirelessRemoteSystem.IsRemote(x) && WirelessRemoteSystem.IsLinked(x))) : null);
			if (val != null)
			{
				WirelessRemoteSystem.OpenLinkedFromKey(val);
				return;
			}
			Ray val2 = default(Ray);
			((Ray)(ref val2))..ctor(((Character)localPlayer).GetEyePoint(), ((Character)localPlayer).GetLookDir());
			RaycastHit val3 = default(RaycastHit);
			if (Physics.Raycast(val2, ref val3, 5f))
			{
				StorageCore componentInParent = ((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<StorageCore>();
				if (!((Object)(object)componentInParent == (Object)null))
				{
					OpenCore(componentInParent);
				}
			}
		}

		internal void OpenCore(StorageCore core)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)core == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				if (_open)
				{
					Close();
				}
				_core = core;
				_open = true;
				IsOpen = true;
				_search = "";
				_scroll = Vector2.zero;
				_craftScroll = Vector2.zero;
				LoadAndClampWindowLayout();
				GUIManager.BlockInput(true);
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
				_recipesCached = false;
				RefreshCache(force: true);
				TryShowPlayerInventory();
				MagicStoragePlugin.Log.LogInfo((object)"v0.1.38 UI: opened Core; Jotunn gameplay input block enabled; network cache initialized.");
			}
		}

		private void TryShowPlayerInventory()
		{
			try
			{
				InventoryGui instance = InventoryGui.instance;
				if ((Object)(object)instance == (Object)null)
				{
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "Show", new Type[2]
				{
					typeof(Container),
					typeof(int)
				}, (Type[])null);
				if (methodInfo != null)
				{
					methodInfo.Invoke(instance, new object[2] { null, 0 });
					_openedPlayerInventory = true;
					MagicStoragePlugin.Log.LogInfo((object)"v1.1.2: opened vanilla player inventory with InventoryGui.Show(Container,int).");
					return;
				}
				MethodInfo[] methods = typeof(InventoryGui).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo2 in methods)
				{
					if (methodInfo2.Name != "Show")
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo2.GetParameters();
					if (parameters.Length != 0 && !(parameters[0].ParameterType != typeof(Container)))
					{
						object[] array = new object[parameters.Length];
						array[0] = null;
						for (int j = 1; j < parameters.Length; j++)
						{
							array[j] = (parameters[j].HasDefaultValue ? parameters[j].DefaultValue : ((parameters[j].ParameterType == typeof(int)) ? ((object)0) : null));
						}
						methodInfo2.Invoke(instance, array);
						_openedPlayerInventory = true;
						MagicStoragePlugin.Log.LogInfo((object)$"v1.1.2: opened vanilla inventory using compatible {methodInfo2}.");
						return;
					}
				}
				MagicStoragePlugin.Log.LogWarning((object)"v1.1.2: no compatible InventoryGui.Show(Container,...) overload found.");
			}
			catch (Exception ex)
			{
				MagicStoragePlugin.Log.LogWarning((object)("Could not auto-open player inventory: " + ex.Message));
			}
		}

		private void Close()
		{
			if (_layoutLoaded)
			{
				SaveWindowLayout();
			}
			_open = false;
			IsOpen = false;
			_core = null;
			_cachedContainers.Clear();
			_cachedItems.Clear();
			ClearStorageDrag();
			if (_openedPlayerInventory)
			{
				try
				{
					AccessTools.Method(typeof(InventoryGui), "Hide", Type.EmptyTypes, (Type[])null)?.Invoke(InventoryGui.instance, null);
				}
				catch
				{
				}
				_openedPlayerInventory = false;
			}
			GUIManager.BlockInput(false);
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				Cursor.visible = false;
				Cursor.lockState = (CursorLockMode)1;
			}
			MagicStoragePlugin.Log.LogInfo((object)"v0.1.38 UI: closed; Jotunn gameplay input block released.");
		}

		private void RefreshCache(bool force = false)
		{
			if (!_open || (Object)(object)_core == (Object)null || (!force && Time.unscaledTime < _nextRefresh))
			{
				return;
			}
			_nextRefresh = Time.unscaledTime + 1f;
			_cachedContainers.Clear();
			_cachedContainers.AddRange(StorageNetwork.FindUnits(_core));
			StorageNetwork.RefreshNetworkState(_cachedContainers);
			_cachedItems.Clear();
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			Dictionary<string, Sprite> dictionary2 = new Dictionary<string, Sprite>();
			Dictionary<string, ItemData> dictionary3 = new Dictionary<string, ItemData>();
			foreach (Container cachedContainer in _cachedContainers)
			{
				if ((Object)(object)cachedContainer == (Object)null || cachedContainer.GetInventory() == null)
				{
					continue;
				}
				foreach (ItemData allItem in cachedContainer.GetInventory().GetAllItems())
				{
					if (allItem?.m_shared != null)
					{
						string name = allItem.m_shared.m_name;
						dictionary[name] = (dictionary.TryGetValue(name, out var value) ? (value + allItem.m_stack) : allItem.m_stack);
						if (!dictionary2.ContainsKey(name) && (Object)(object)allItem.GetIcon() != (Object)null)
						{
							dictionary2[name] = allItem.GetIcon();
						}
						if (!dictionary3.ContainsKey(name))
						{
							dictionary3[name] = allItem.Clone();
						}
					}
				}
			}
			_storedCounts.Clear();
			foreach (KeyValuePair<string, int> item in dictionary)
			{
				_storedCounts[item.Key] = item.Value;
			}
			foreach (KeyValuePair<string, int> item2 in dictionary)
			{
				string text = ((Localization.instance != null) ? Localization.instance.Localize(item2.Key) : item2.Key);
				if (string.IsNullOrWhiteSpace(text) || text == item2.Key)
				{
					text = (item2.Key.StartsWith("$item_") ? item2.Key.Substring(6).Replace("_", " ") : item2.Key);
				}
				_cachedItems.Add(new ItemSummary
				{
					Name = item2.Key,
					DisplayName = text,
					Count = item2.Value,
					Icon = (dictionary2.TryGetValue(item2.Key, out var value2) ? value2 : null),
					Sample = (dictionary3.TryGetValue(item2.Key, out var value3) ? value3 : null)
				});
			}
			_cachedItems.Sort((ItemSummary a, ItemSummary b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase));
		}

		private Texture2D MakeTexture(Color color)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			val.SetPixels((Color[])(object)new Color[4] { color, color, color, color });
			val.Apply();
			((Texture)val).wrapMode = (TextureWrapMode)1;
			return val;
		}

		private void EnsureValheimTheme()
		{
			//IL_0029: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			//IL_00c2: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Expected O, but got Unknown
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Expected O, but got Unknown
			if (_panelStyle == null)
			{
				_panelTexture = MakeTexture(new Color(0.1f, 0.075f, 0.045f, 0.92f));
				_buttonTexture = MakeTexture(new Color(0.22f, 0.145f, 0.075f, 0.98f));
				_buttonActiveTexture = MakeTexture(new Color(0.38f, 0.245f, 0.105f, 1f));
				_title = new GUIStyle(GUI.skin.label)
				{
					fontSize = 25,
					fontStyle = (FontStyle)1
				};
				_title.normal.textColor = new Color(0.93f, 0.79f, 0.52f);
				_button = new GUIStyle(GUI.skin.button)
				{
					fontSize = 15,
					fontStyle = (FontStyle)1
				};
				_button.normal.background = _buttonTexture;
				_button.hover.background = _buttonActiveTexture;
				_button.normal.textColor = new Color(0.92f, 0.84f, 0.68f);
				_panelStyle = new GUIStyle(GUI.skin.box);
				_panelStyle.normal.background = _panelTexture;
				_panelStyle.normal.textColor = new Color(0.9f, 0.82f, 0.68f);
				_slotStyle = new GUIStyle(_button);
				_slotStyle.fontSize = 13;
				_tabStyle = new GUIStyle(_button);
				_tabActiveStyle = new GUIStyle(_button);
				_tabActiveStyle.normal.background = _buttonActiveTexture;
			}
		}

		private void LoadAndClampWindowLayout()
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			if (!_layoutLoaded)
			{
				float num = Mathf.Clamp(MagicStoragePlugin.WindowWidth.Value, 645f, Mathf.Max(645f, (float)Screen.width - 16f));
				float num2 = Mathf.Clamp(MagicStoragePlugin.WindowHeight.Value, 450f, Mathf.Max(450f, (float)Screen.height - 16f));
				float value = MagicStoragePlugin.WindowX.Value;
				float num3 = MagicStoragePlugin.WindowY.Value;
				if (num3 < 0f)
				{
					num3 = Mathf.Clamp((float)Screen.height * 0.34f, 8f, Mathf.Max(8f, (float)Screen.height - num2 - 8f));
				}
				_window = new Rect(value, num3, num, num2);
				_layoutLoaded = true;
			}
			ClampWindowToScreen();
		}

		private void ClampWindowToScreen()
		{
			((Rect)(ref _window)).width = Mathf.Clamp(((Rect)(ref _window)).width, 645f, Mathf.Max(645f, (float)Screen.width - 16f));
			((Rect)(ref _window)).height = Mathf.Clamp(((Rect)(ref _window)).height, 450f, Mathf.Max(450f, (float)Screen.height - 16f));
			((Rect)(ref _window)).x = Mathf.Clamp(((Rect)(ref _window)).x, 0f, Mathf.Max(0f, (float)Screen.width - ((Rect)(ref _window)).width));
			((Rect)(ref _window)).y = Mathf.Clamp(((Rect)(ref _window)).y, 0f, Mathf.Max(0f, (float)Screen.height - ((Rect)(ref _window)).height));
		}

		private void SaveWindowLayout()
		{
			MagicStoragePlugin.WindowX.Value = ((Rect)(ref _window)).x;
			MagicStoragePlugin.WindowY.Value = ((Rect)(ref _window)).y;
			MagicStoragePlugin.WindowWidth.Value = ((Rect)(ref _window)).width;
			MagicStoragePlugin.WindowHeight.Value = ((Rect)(ref _window)).height;
		}

		private void HandleWindowInteraction()
		{
			//IL_006b: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Invalid comparison between Unknown and I4
			//IL_00f6: 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)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: 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_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: 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_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Invalid comparison between Unknown and I4
			//IL_0240: 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_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Invalid comparison between Unknown and I4
			Event current = Event.current;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref _window)).width - 24f, ((Rect)(ref _window)).height - 24f, 20f, 20f);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(0f, 0f, Mathf.Max(0f, ((Rect)(ref _window)).width - 30f), 46f);
			GUI.Box(val, "↘");
			if ((int)current.type == 0 && current.button == 0)
			{
				if (((Rect)(ref val)).Contains(current.mousePosition))
				{
					_resizing = true;
					_movingWindow = false;
					_resizeStartMouse = GUIUtility.GUIToScreenPoint(current.mousePosition);
					_resizeStartSize = new Vector2(((Rect)(ref _window)).width, ((Rect)(ref _window)).height);
					current.Use();
					return;
				}
				if (((Rect)(ref val2)).Contains(current.mousePosition))
				{
					_movingWindow = true;
					_resizing = false;
					_moveStartMouse = GUIUtility.GUIToScreenPoint(current.mousePosition);
					_moveStartPosition = new Vector2(((Rect)(ref _window)).x, ((Rect)(ref _window)).y);
					current.Use();
					return;
				}
			}
			if (_resizing && (int)current.type == 3)
			{
				Vector2 val3 = GUIUtility.GUIToScreenPoint(current.mousePosition);
				Vector2 val4 = val3 - _resizeStartMouse;
				((Rect)(ref _window)).width = Mathf.Clamp(_resizeStartSize.x + val4.x, 645f, Mathf.Max(645f, (float)Screen.width - ((Rect)(ref _window)).x));
				((Rect)(ref _window)).height = Mathf.Clamp(_resizeStartSize.y + val4.y, 450f, Mathf.Max(450f, (float)Screen.height - ((Rect)(ref _window)).y));
				current.Use();
			}
			else if (_movingWindow && (int)current.type == 3)
			{
				Vector2 val5 = GUIUtility.GUIToScreenPoint(current.mousePosition);
				Vector2 val6 = val5 - _moveStartMouse;
				((Rect)(ref _window)).x = _moveStartPosition.x + val6.x;
				((Rect)(ref _window)).y = _moveStartPosition.y + val6.y;
				ClampWindowToScreen();
				current.Use();
			}
			else if ((_resizing || _movingWindow) && (int)current.type == 1)
			{
				_resizing = false;
				_movingWindow = false;
				ClampWindowToScreen();
				SaveWindowLayout();
				current.Use();
			}
		}

		private void OnGUI()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_0083: 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)
			if (_open && !((Object)(object)_core == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
				EnsureValheimTheme();
				GUIStyle window = GUI.skin.window;
				GUI.skin.window = _panelStyle;
				Rect window2 = _window;
				_window = GUI.Window(39173, _window, new WindowFunction(DrawWindow), "");
				ClampWindowToScreen();
				GUI.skin.window = window;
				if (!_resizing && (Mathf.Abs(((Rect)(ref window2)).x - ((Rect)(ref _window)).x) > 0.1f || Mathf.Abs(((Rect)(ref window2)).y - ((Rect)(ref _window)).y) > 0.1f))
				{
					SaveWindowLayout();
				}
				DrawStorageDragGhost();
			}
		}

		private void DrawItemDetailsPanel(ItemSummary item, Rect panel)
		{
			//IL_0001: 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_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Expected O, but got Unknown
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			GUI.Box(panel, "Item Details", _panelStyle);
			float num = 15f;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref panel)).x + num, ((Rect)(ref panel)).y + 30f, Mathf.Max(80f, ((Rect)(ref panel)).width - num * 2f), Mathf.Max(60f, ((Rect)(ref panel)).height - 40f));
			if (item?.Sample?.m_shared == null)
			{
				GUI.Label(val, "Hover over an item to see its Valheim tooltip, weight and stored amount.");
				return;
			}
			string text;
			try
			{
				text = item.Sample.GetTooltip(-1);
				if (Localization.instance != null)
				{
					text = Localization.instance.Localize(text);
				}
			}
			catch
			{
				string text2 = item.Sample.m_shared.m_description ?? "";
				if (Localization.instance != null)
				{
					text2 = Localization.instance.Localize(text2);
				}
				text = text2 + $"\n\nWeight: {item.Sample.m_shared.m_weight:0.0}";
			}
			text += $"\n\nStored: {item.Count}";
			GUIStyle val2 = new GUIStyle(GUI.skin.label)
			{
				richText = true,
				wordWrap = true,
				alignment = (TextAnchor)0
			};
			GUI.Label(val, "<b>" + item.DisplayName + "</b>\n" + text, val2);
		}

		private string StationKey(CraftingStation station)
		{
			if ((Object)(object)station == (Object)null)
			{
				return "";
			}
			return ((Object)((Component)station).gameObject).name.Replace("(Clone)", "");
		}

		private bool PlayerKnowsRecipe(Recipe recipe)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || recipe?.m_item?.m_itemData?.m_shared == null)
			{
				return false;
			}
			string name = recipe.m_item.m_itemData.m_shared.m_name;
			string name2 = ((Object)recipe.m_item).name;
			try
			{
				if (AccessTools.Field(typeof(Player), "m_knownRecipes")?.GetValue(localPlayer) is ICollection<string> collection)
				{
					return collection.Contains(name) || collection.Contains(name2);
				}
				MethodInfo methodInfo = AccessTools.Method(typeof(Player), "IsRecipeKnown", new Type[1] { typeof(string) }, (Type[])null);
				if (methodInfo != null)
				{
					return (bool)methodInfo.Invoke(localPlayer, new object[1] { name }) || (bool)methodInfo.Invoke(localPlayer, new object[1] { name2 });
				}
			}
			catch (Exception ex)
			{
				MagicStoragePlugin.Log.LogWarning((object)("Recipe knowledge check failed for " + name2 + ": " + ex.Message));
			}
			return false;
		}

		private bool PlayerHasDiscoveredRecipeMaterials(Recipe recipe)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)recipe == (Object)null)
			{
				return false;
			}
			try
			{
				if (!(AccessTools.Field(typeof(Player), "m_knownMaterial")?.GetValue(localPlayer) is ICollection<string> collection))
				{
					return false;
				}
				foreach (Requirement item in ActiveCraftRequirements(recipe))
				{
					SharedData val = item?.m_resItem?.m_itemData?.m_shared;
					if (val != null)
					{
						string name = val.m_name;
						string name2 = ((Object)item.m_resItem).name;
						if (!collection.Contains(name) && !collection.Contains(name2))
						{
							return false;
						}
					}
				}
				return true;
			}
			catch (Exception ex)
			{
				MagicStoragePlugin.Log.LogWarning((object)("Recipe material-knowledge check failed: " + ex.Message));
				return false;
			}
		}

		private void CacheStationsAndRecipes()
		{
			//IL_00de: 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)
			_stationLevels.Clear();
			_stationFilters.Clear();
			_stationFilters.Add("All");
			_cachedRecipes.Clear();
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)_core == (Object)null || (Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			try
			{
				AccessTools.Method(typeof(Player), "UpdateKnownRecipesList", (Type[])null, (Type[])null)?.Invoke(localPlayer, null);
			}
			catch (Exception ex)
			{
				MagicStoragePlugin.Log.LogWarning((object)("v1.1.2: could not refresh known recipes: " + ex.Message));
			}
			List<CraftingStation> list = new List<CraftingStation>();
			CraftingStation[] array = Object.FindObjectsByType<CraftingStation>((FindObjectsSortMode)0);
			foreach (CraftingStation val in array)
			{
				if (!((Object)(object)val == (Object)null) && !(Vector3.Distance(((Component)_core).transform.position, ((Component)val).transform.position) > MagicStoragePlugin.NetworkRadius.Value))
				{
					list.Add(val);
					string key = StationKey(val);
					int num = 1;
					try
					{
						num = Math.Max(1, Convert.ToInt32(AccessTools.Method(typeof(CraftingStation), "GetLevel", (Type[])null, (Type[])null)?.Invoke(val, null) ?? ((object)1)));
					}
					catch
					{
					}
					if (!_stationLevels.TryGetValue(key, out var value) || num > value)
					{
						_stationLevels[key] = num;
					}
				}
			}
			list = (from @group in list.GroupBy(StationKey)
				select @group.OrderByDescending(delegate(CraftingStation station)
				{
					try
					{
						return Math.Max(1, Convert.ToInt32(AccessTools.Method(typeof(CraftingStation), "GetLevel", (Type[])null, (Type[])null)?.Invoke(station, null) ?? ((object)1)));
					}
					catch
					{
						return 1;
					}
				}).First()).ToList();
			int num2 = 0;
			MethodInfo methodInfo = AccessTools.Method(typeof(Player), "SetCraftingStation", new Type[1] { typeof(CraftingStation) }, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Player), "GetAvailableRecipes", new Type[1] { typeof(List<Recipe>).MakeByRefType() }, (Type[])null);
			CraftingStation val2 = null;
			try
			{
				val2 = localPlayer.GetCurrentCraftingStation();
			}
			catch
			{