Decompiled source of ZenItemStands v1.0.2

plugins/ZenItemStands.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using Zen;
using Zen.Compatibility;
using Zen.Lib;
using Zen.Lib.Config;
using ZenItemStands.Compatibility;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenItemStands")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenItemStands")]
[assembly: AssemblyCopyright("Copyright \ufffd  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ZenItemStands
{
	internal class ArmorStandInventory : StandInventory
	{
		private ArmorStand _stand;

		private static readonly StringBuilder Sb = new StringBuilder();

		protected override void Awake()
		{
			if (!((Component)this).TryGetComponent<ArmorStand>(ref _stand))
			{
				throw new Exception("ArmorStand component not found on " + ((Object)this).name);
			}
			SetupInventory(_stand.m_name, _stand.m_slots.Count, 1);
			((Component)this).GetComponentInChildren<Switch>().m_name = _stand.m_name;
			base.Awake();
		}

		public override void ShowErrorMessage()
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, "$piece_armorstand_cantattach", 0, (Sprite)null);
		}

		protected override bool IsSameType(ItemData armorItem, ItemData compareItem)
		{
			ArmorStandSlot slot = GetSlot(armorItem);
			if (slot != null)
			{
				return _stand.CanAttach(slot, compareItem);
			}
			return false;
		}

		private ArmorStandSlot? GetSlot(ItemData item)
		{
			return ((IEnumerable<ArmorStandSlot>)_stand.m_slots).FirstOrDefault((Func<ArmorStandSlot, bool>)((ArmorStandSlot slot) => slot.m_currentItemName == ItemDataExt.GetName(item)));
		}

		private ItemData? GetAttachedItemData(int index)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			string attachedItem = _stand.GetAttachedItem(index);
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(14, 2, ref flag);
			if (flag)
			{
				val.AppendLiteral("Index: ");
				val.AppendFormatted<int>(index);
				val.AppendLiteral(" Item: ");
				val.AppendFormatted(attachedItem);
			}
			Logging<Plugin>.Debug(val, 0);
			return GetItemDataFromZDO(attachedItem, index);
		}

		protected override bool IsStandInventoryDiff()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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)
			int num = 0;
			bool flag = default(bool);
			for (int i = 0; i < _stand.m_slots.Count; i++)
			{
				ItemData attachedItemData = GetAttachedItemData(i);
				if (attachedItemData == null)
				{
					continue;
				}
				if (!InventoryExt.HaveItemData(((VirtualInventory)this).Inventory, attachedItemData))
				{
					InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(11, 1, ref flag);
					if (flag)
					{
						val.AppendLiteral("Diff Item: ");
						val.AppendFormatted(ItemDataExt.GetName(attachedItemData));
					}
					Logging<Plugin>.Info(val, 0);
					return true;
				}
				num++;
			}
			bool num2 = num != ((VirtualInventory)this).Inventory.NrOfItems();
			if (!num2)
			{
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(41, 1, ref flag);
				if (flag)
				{
					val.AppendLiteral("Container and stand are identical: ");
					val.AppendFormatted<int>(num);
					val.AppendLiteral(" items");
				}
				Logging<Plugin>.Debug(val, 0);
			}
			return num2;
		}

		protected override bool CanAttach(ItemData item, bool ignoreExisting)
		{
			int index;
			return CanAttach(item, out index, ignoreExisting);
		}

		private bool CanAttach(ItemData item, out int index, bool ignoreExisting)
		{
			index = -1;
			for (int i = 0; i < _stand.m_slots.Count; i++)
			{
				if (CanAttachAt(i))
				{
					index = i;
					return true;
				}
			}
			return false;
			bool CanAttachAt(int num)
			{
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: Invalid comparison between Unknown and I4
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Invalid comparison between Unknown and I4
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				ArmorStandSlot val = _stand.m_slots[num];
				if (!_stand.CanAttach(val, item))
				{
					return false;
				}
				if (!ignoreExisting && _stand.HaveAttachment(num))
				{
					return false;
				}
				ItemType itemType = item.m_shared.m_itemType;
				if (((int)itemType == 7 || (int)itemType == 11) ? true : false)
				{
					return true;
				}
				foreach (Transform item2 in item.m_dropPrefab.transform)
				{
					if (((Object)item2).name.StartsWith("attach"))
					{
						return true;
					}
				}
				return false;
			}
		}

		protected override bool CanSwap(ItemData externItem, out ItemData swapItem)
		{
			if (CanAttach(externItem, ignoreExisting: true))
			{
				foreach (ItemData allItem in ((VirtualInventory)this).Inventory.GetAllItems())
				{
					if (IsSameType(allItem, externItem))
					{
						swapItem = allItem;
						return true;
					}
				}
			}
			swapItem = null;
			return false;
		}

		public override void SwapEquip()
		{
			Inventory inventory = ((VirtualInventory)this).Inventory;
			Player localPlayer = Player.m_localPlayer;
			List<ItemData> equippedItems = ((Humanoid)localPlayer).GetInventory().GetEquippedItems();
			if (((Humanoid)localPlayer).m_hiddenLeftItem != null)
			{
				equippedItems.Add(((Humanoid)localPlayer).m_hiddenLeftItem);
			}
			if (((Humanoid)localPlayer).m_hiddenRightItem != null)
			{
				equippedItems.Add(((Humanoid)localPlayer).m_hiddenRightItem);
			}
			ItemData[] array = inventory.GetAllItems().ToArray();
			foreach (ItemData standItem in array)
			{
				EquipItemSwap(localPlayer, standItem);
			}
			((Humanoid)localPlayer).HideHandItems(false, false);
			Inventory inventory2 = ((Humanoid)localPlayer).GetInventory();
			foreach (ItemData item in equippedItems)
			{
				if (inventory2.ContainsItem(item) && CanAttach(item, ignoreExisting: false))
				{
					((Humanoid)localPlayer).UnequipItem(item, false);
					inventory.MoveItemToThis(inventory2, item);
				}
			}
		}

		private bool AttachItem(ItemData item)
		{
			if (!CanAttach(item, out var index, ignoreExisting: false))
			{
				return false;
			}
			base.Nview.ClaimOwnership();
			ZDO zDO = base.Nview.GetZDO();
			zDO.Set(index + "_item", ((Object)item.m_dropPrefab).name);
			ItemDrop.SaveToZDO(index, item, zDO);
			return true;
		}

		protected override void UpdateVisualFromContainer()
		{
			//IL_0055: 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_0072: 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)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			if (IsStandInventoryDiff())
			{
				Logging<Plugin>.Info("Updating visuals and slot data", 0);
				ClearArmorStand();
				int num = ((VirtualInventory)this).Inventory.GetAllItems().Count(AttachItem);
				_stand.UpdateVisual();
				Transform transform = ((Component)this).transform;
				_stand.m_effects.Create(transform.position, transform.rotation, (Transform)null, 1f, -1);
				bool flag = default(bool);
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(29, 2, ref flag);
				if (flag)
				{
					val.AppendFormatted("ArmorStand");
					val.AppendLiteral(" loaded ");
					val.AppendFormatted<int>(num);
					val.AppendLiteral(" items from container");
				}
				Logging<Plugin>.Info(val, 0);
			}
		}

		private void ClearArmorStand()
		{
			for (int i = 0; i < _stand.m_slots.Count; i++)
			{
				if (base.Nview.IsOwner())
				{
					base.Nview.GetZDO().Set(i + "_item", string.Empty);
				}
				_stand.SetVisualItem(i, string.Empty, 0);
			}
			_stand.UpdateSupports();
		}

		protected override void LoadInventory()
		{
			//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)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			Logging<Plugin>.Info("Fill inventory from slots", 0);
			bool flag = default(bool);
			for (int i = 0; i < _stand.m_slots.Count; i++)
			{
				if (!_stand.HaveAttachment(i))
				{
					continue;
				}
				ItemData attachedItemData = GetAttachedItemData(i);
				if (attachedItemData != null)
				{
					((VirtualInventory)this).Inventory.AddItem(attachedItemData);
					InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(46, 1, ref flag);
					if (flag)
					{
						val.AppendLiteral("Added item to container from ArmorStand slot: ");
						val.AppendFormatted(ItemDataExt.GetName(attachedItemData));
					}
					Logging<Plugin>.Info(val, 0);
				}
			}
		}

		protected override bool IsStackAllButtonVisible()
		{
			if (Configs.EnableArmorStandEquipButton.Value)
			{
				return !Conflict.IsConflict;
			}
			return false;
		}

		protected override bool CanHoldToEquip()
		{
			if (!Conflict.IsConflict)
			{
				return Configs.EnableArmorStandHoldToEquip.Value;
			}
			return false;
		}

		public void ValidatePose()
		{
			if (Configs.EnableArmorStandPoseChange.Value && !_stand.HasChestAndLegItem())
			{
				_stand.ResetPose();
			}
		}

		public override string GetHoverText()
		{
			Sb.Clear();
			Sb.Append(base.GetHoverText());
			if (WardAccessExt.CanAccessWard((MonoBehaviour)(object)this, false) && Configs.EnableArmorStandPoseChange.Value && _stand.HasChestAndLegItem())
			{
				Sb.Append(StringExt.Localize("\n" + UI.PromptInteractAlt + " $hud_changeorientation"));
			}
			return Sb.ToString();
		}
	}
	internal static class ArmorStandExt
	{
		public static void ResetPose(this ArmorStand armorStand)
		{
			if (armorStand.m_pose != 0)
			{
				armorStand.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_SetPose", new object[1] { 0 });
			}
		}

		public static void NextPose(this ArmorStand armorStand)
		{
			armorStand.m_nview.InvokeRPC(ZNetView.Everybody, "RPC_SetPose", new object[1] { (armorStand.m_pose + 1) % armorStand.m_poseCount });
		}

		public static bool HasChestAndLegItem(this ArmorStand armorStand)
		{
			bool flag = false;
			bool flag2 = false;
			for (int i = 0; i < armorStand.m_slots.Count; i++)
			{
				string attachedItem = armorStand.GetAttachedItem(i);
				if (!Utility.IsNullOrWhiteSpace(attachedItem))
				{
					ItemDrop component = ObjectDB.instance.GetItemPrefab(attachedItem).GetComponent<ItemDrop>();
					if (ItemDataExt.IsItemType(component.m_itemData, (ItemType)7))
					{
						flag = true;
					}
					if (ItemDataExt.IsItemType(component.m_itemData, (ItemType)11))
					{
						flag2 = true;
					}
					if (flag && flag2)
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class ArmorStandPatch
	{
		[HarmonyPatch(typeof(ArmorStand), "SetPose")]
		private static class ArmorStandSetPose
		{
			[UsedImplicitly]
			private static void Prefix(ref bool effect)
			{
				effect = false;
			}

			[UsedImplicitly]
			private static void Postfix(ArmorStand __instance)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				__instance.UpdateSupports();
				bool flag = default(bool);
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(8, 2, ref flag);
				if (flag)
				{
					val.AppendFormatted("SetPose");
					val.AppendLiteral(" index: ");
					val.AppendFormatted<int>(__instance.m_pose);
				}
				Logging<Plugin>.Info(val, 0);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ArmorStand), "Awake")]
		private static void ArmorStand_Awake(ArmorStand __instance)
		{
			if (((MonoBehaviour)(object)__instance).HasStandInventory(out StandInventory _) && !Configs.EnableArmorStandPoseChange.Value)
			{
				__instance.ResetPose();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Switch), "GetHoverText")]
		private static void ArmorStand_Switch_GetHoverText(Switch __instance, ref string __result)
		{
			ArmorStand componentInParent = ((Component)__instance).GetComponentInParent<ArmorStand>();
			if (Object.op_Implicit((Object)(object)componentInParent) && ((MonoBehaviour)(object)componentInParent).HasStandInventory(out StandInventory si))
			{
				__result = si.GetHoverText();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ArmorStand), "UpdateSupports")]
		private static void ArmorStand_UpdateSupports(ArmorStand __instance)
		{
			if (!Configs.EnableArmorStandPoseChange.Value)
			{
				return;
			}
			if (__instance.m_supports.Count == 0)
			{
				Logging<Plugin>.Warning((object)"m_supports is length 0 when it should be at least 1, aborting.", 0);
				return;
			}
			ArmorStandSupport obj = __instance.m_supports[0];
			int pose = __instance.m_pose;
			foreach (GameObject support in obj.m_supports)
			{
				support.SetActive(pose == 0);
			}
			((Component)((Component)__instance).transform.Find("New/Lod1/ArmorStand")).gameObject.SetActive(pose < 4);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Switch), "Interact")]
		private static void ArmorStand_Switch_Interact(Switch __instance, Humanoid character, bool hold, bool alt, ref bool __result, ref bool __runOriginal)
		{
			ArmorStand componentInParent = ((Component)__instance).GetComponentInParent<ArmorStand>();
			if (!Object.op_Implicit((Object)(object)componentInParent) || !((MonoBehaviour)(object)componentInParent).HasStandInventory(out StandInventory si))
			{
				return;
			}
			__runOriginal = false;
			if (!hold)
			{
				__result = true;
			}
			if (alt && Configs.EnableArmorStandPoseChange.Value)
			{
				if (!hold)
				{
					componentInParent.NextPose();
				}
			}
			else
			{
				si.Open();
				Game.instance.IncrementPlayerStat((PlayerStatType)25, 1f);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ArmorStand), "UseItem")]
		private static void ArmorStand_UseItem(ArmorStand __instance, ref bool __result, ref bool __runOriginal)
		{
			if (((MonoBehaviour)(object)__instance).HasStandInventory(out StandInventory si) && !si.CanUseHotbarItem())
			{
				__runOriginal = false;
				__result = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ArmorStand), "RPC_DropItemByName")]
		private static void ArmorStand_RPC_DropItemByName(ArmorStand __instance)
		{
			if (((MonoBehaviour)(object)__instance).IsThisStandOpen())
			{
				InventoryGui.instance.Hide();
			}
		}
	}
	internal static class Configs
	{
		private const string SECTION_GENERAL = "General";

		public static readonly ConfigEntry<StringList> StandPrefabNames;

		public static readonly ConfigEntry<bool> EnableHotbarUseItem;

		private const string SECTION_ARMORSTAND = "Piece: ArmorStand";

		public static readonly ConfigEntry<bool> EnableArmorStandPoseChange;

		public static readonly ConfigEntry<bool> EnableArmorStandHoldToEquip;

		public static readonly ConfigEntry<bool> EnableArmorStandEquipButton;

		public static readonly ConfigEntry<bool> EnableArmorStandAmericanSpelling;

		private const string SECTION_ITEMSTAND = "Piece: ItemStand";

		public static readonly ConfigEntry<bool> EnableItemStandEquipButton;

		public static readonly ConfigEntry<bool> ShowItemOnStandName;

		static Configs()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_0046: Expected O, but got Unknown
			StringList val = new StringList();
			((List<string>)val).Add("itemstand");
			((List<string>)val).Add("itemstandh");
			((List<string>)val).Add("ArmorStand");
			((List<string>)val).Add("Placeable_HardRock");
			StandPrefabNames = Config.Define<StringList>(true, "General", "Stand Prefabs", val, "List of all the prefabs that are item stands or armor stands.\nThese prefabs must have an ItemStand or ArmorStand component attached to them.");
			EnableHotbarUseItem = Config.Define<bool>(true, "General", "Enable Hotbar Use Item", false, "If enabled you can also use traditional 1-8 hotbar buttons to assign items to stands (Vanilla: true)");
			EnableArmorStandPoseChange = Config.Define<bool>(true, "Piece: ArmorStand", "Enable Pose Changing", false, "Enable changing poses of armor stands.  NOTE: Stand must have chest and legs armor.");
			EnableArmorStandHoldToEquip = Config.Define<bool>(true, "Piece: ArmorStand", "Enable Hold To Equip", false, "Should (Hold to equip) be available on Armor Stands hover text?");
			EnableArmorStandEquipButton = Config.Define<bool>(true, "Piece: ArmorStand", "Enable Use/Equip Button", true, "Enable the use/equip button on armor stands to quickly swap equipped gear.");
			EnableArmorStandAmericanSpelling = Config.Define<bool>(false, "Piece: ArmorStand", "American Spelling", true, "Change the spelling to 'Armor Stand' instead of 'Armour Stand'\r\n[Restart required for changes to take effect]");
			EnableItemStandEquipButton = Config.Define<bool>(true, "Piece: ItemStand", "Enable Use/Equip Button", true, "Enable the use/equip button on item stands to quickly swap equipped gear.");
			ShowItemOnStandName = Config.Define<bool>(true, "Piece: ItemStand", "Show Item Name", true, "Show the name of the item on the stand in the hover text (Vanilla: true)\r\n[ZenHoverItem overrides this option]");
		}
	}
	internal static class ItemStandExt
	{
		public static bool HasOrientations(this ItemStand itemStand)
		{
			return itemStand.m_orientationSettings.Count > 1;
		}
	}
	[HarmonyPatch]
	internal static class PetRock
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(Pet), "GetHoverText")]
		private static void Pet_GetHoverText(Pet __instance, ref string __result, ref bool __runOriginal)
		{
			if (((MonoBehaviour)(object)__instance).HasStandInventory(out StandInventory _))
			{
				__runOriginal = false;
				if (!WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, false))
				{
					__result = __instance.m_tameable.GetHoverName();
					__result += StringExt.Localize("\n" + UI.PromptInteract + " $hud_pet");
				}
				else
				{
					__result += __instance.m_tameable.GetHoverText();
					__result = __result.Replace(StringExt.Localize(">] $hud_pet"), StringExt.Localize(">] $hud_pet ($msg_hold_equip_hover)"));
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Pet), "Interact")]
		private static void Pet_Interact(Pet __instance, Humanoid user, bool alt, bool hold, ref bool __result, ref bool __runOriginal)
		{
			if (((MonoBehaviour)(object)__instance).HasStandInventory(out StandInventory si))
			{
				__runOriginal = false;
				if (alt)
				{
					__instance.m_tameable.Interact(user, false, true);
				}
				else if (hold)
				{
					si.SetLabel(__instance.m_tameable.GetHoverName());
					__instance.m_itemStand.Interact(user, false, false);
				}
				else
				{
					__instance.m_tameable.Interact(user, false, false);
				}
			}
		}
	}
	internal static class Startup
	{
		public static List<StandInventory> InitPrefabs()
		{
			Logging<Plugin>.Info("Initializing Prefabs", 0);
			return Init(from p in ((IEnumerable<string>)Configs.StandPrefabNames.Value).Select((Func<string, GameObject>)ZNetScene.instance.GetPrefab)
				where (Object)(object)p != (Object)null
				select p);
		}

		public static List<StandInventory> Init(IEnumerable<GameObject> gameObjects)
		{
			//IL_001b: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			List<StandInventory> list = new List<StandInventory>();
			bool flag = default(bool);
			foreach (GameObject gameObject in gameObjects)
			{
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(14, 1, ref flag);
				if (flag)
				{
					val.AppendLiteral("Initializing: ");
					val.AppendFormatted(((Object)gameObject).name);
				}
				Logging<Plugin>.Info(val, 0);
				if (!list.AddTo<ArmorStand>(gameObject) && !list.AddTo<ItemStand>(gameObject))
				{
					Logging<Plugin>.Error((object)(((Object)gameObject).name + " is not ArmorStand or ItemStand"), (ushort)0);
				}
			}
			return list;
		}

		private static bool AddTo<T>(this List<StandInventory> standInventories, GameObject obj) where T : Component
		{
			T component = obj.GetComponent<T>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return false;
			}
			if (!(component is ArmorStand))
			{
				if (!(component is ItemStand))
				{
					throw new Exception($"Unknown component type: {((object)component).GetType()}");
				}
				standInventories.Add(AddInv<ItemStandInventory>(obj));
			}
			else
			{
				standInventories.Add(AddInv<ArmorStandInventory>(obj));
			}
			return true;
		}

		private static T AddInv<T>(GameObject targetObject) where T : StandInventory
		{
			T val = targetObject.AddComponent<T>();
			((ZenMod<Plugin>)(object)ZenMod<Plugin>.Instance).HotLoad.Track((Object)(object)val);
			return val;
		}
	}
	internal static class StandInventoryExt
	{
		public static bool HasStandInventory(this MonoBehaviour comp, out StandInventory si)
		{
			return ((Component)comp).TryGetComponent<StandInventory>(ref si);
		}

		public static bool IsThisStandOpen(this MonoBehaviour comp)
		{
			return VirtualInventory.IsOpenedFrom(((Component)comp).gameObject);
		}
	}
	internal abstract class StandInventory : VirtualInventory
	{
		[HarmonyPatch]
		private static class Patch
		{
			[HarmonyPatch(typeof(InventoryGui), "OnStackAll")]
			private static class InventoryGuiOnStackAll
			{
				private static bool _isButtonPressed;

				[UsedImplicitly]
				private static void Prefix()
				{
					_isButtonPressed = true;
				}

				[UsedImplicitly]
				private static void Postfix()
				{
					_isButtonPressed = false;
				}

				[HarmonyPrefix]
				[HarmonyPatch(typeof(Inventory), "StackAll")]
				[HarmonyPriority(900)]
				private static void Inventory_StackAll(ref bool __runOriginal)
				{
					if (!VirtualInventory.IsOpened<StandInventory>())
					{
						return;
					}
					__runOriginal = false;
					if (_isButtonPressed || (Opened is ArmorStandInventory && Configs.EnableArmorStandHoldToEquip.Value))
					{
						if (Conflict.IsConflict)
						{
							Logging<Plugin>.Warning((object)"Conflicting mod detected, abort equipment swap to protect against item duplication.", 0);
						}
						else
						{
							Opened.SwapEquip();
						}
					}
				}
			}

			[HarmonyPostfix]
			[HarmonyPatch(typeof(InventoryGui), "Hide")]
			private static void InventoryGui_Hide(InventoryGui __instance)
			{
				if (VirtualInventory.IsOpened<StandInventory>() && Opened is ArmorStandInventory armorStandInventory)
				{
					armorStandInventory.ValidatePose();
				}
			}
		}

		private Inventory? _inventory;

		private static readonly StringBuilder Sb = new StringBuilder();

		private static StandInventory Opened
		{
			get
			{
				StandInventory result = default(StandInventory);
				if (!VirtualInventory.TryGetOpened<StandInventory>(ref result))
				{
					throw new Exception("Can not access, not open");
				}
				return result;
			}
		}

		protected override Inventory Inventory => _inventory ?? throw new NullReferenceException();

		protected override string StackAllButtonLabel => "$inventory_use";

		protected ZNetView Nview { get; private set; }

		public abstract void ShowErrorMessage();

		protected abstract bool IsSameType(ItemData standItem, ItemData compareItem);

		protected abstract bool CanAttach(ItemData itemData, bool ignoreExisting);

		protected abstract bool CanSwap(ItemData externItem, out ItemData swapItem);

		public abstract void SwapEquip();

		protected abstract void UpdateVisualFromContainer();

		protected abstract bool CanHoldToEquip();

		protected abstract bool IsStandInventoryDiff();

		protected override bool IsWarded()
		{
			return true;
		}

		protected override bool IsStackAllButtonVisible()
		{
			if (IsAnyItemEquipable())
			{
				return !Conflict.IsConflict;
			}
			return false;
		}

		protected override ZNetView GetZNetView()
		{
			return Nview;
		}

		protected void SetupInventory(string label, int width, int height)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			if (_inventory == null)
			{
				_inventory = new Inventory(label, (Sprite)null, width, height);
				Inventory? inventory = _inventory;
				inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged));
			}
		}

		public void SetLabel(string label)
		{
			if (_inventory != null)
			{
				_inventory.m_name = label;
			}
		}

		protected override void Awake()
		{
			if (!ZNetView.m_forceDisableInit)
			{
				Nview = ((Component)this).GetComponent<ZNetView>();
				((ZenMod<Plugin>)(object)ZenMod<Plugin>.Instance).HotLoad.Track((Object)(object)this);
				((VirtualInventory)this).Awake();
			}
		}

		protected override bool OnHoldToStack()
		{
			if (!CanHoldToEquip())
			{
				return false;
			}
			SwapEquip();
			return true;
		}

		public void Open()
		{
			if (((VirtualInventory)this).IsOpen || VirtualInventory.IsRecentlyClosed)
			{
				Logging<Plugin>.Info("Already open or recently closed, aborting", 0);
			}
			else
			{
				((VirtualInventory)this).RequestOpen();
			}
		}

		protected override void OnOpenAllow()
		{
			InventoryGridExt.ShowAmountText(InventoryGui.instance.ContainerGrid, false, -1);
			Logging<Plugin>.Info("Opened Stand", 0);
		}

		protected override void OnClose()
		{
			Timing.Delay((MonoBehaviour)(object)InventoryGui.instance, 0.5f, (Action)delegate
			{
				InventoryGridExt.ShowAmountText(InventoryGui.instance.ContainerGrid, true, -1);
			});
		}

		private bool IsInUse()
		{
			return false;
		}

		private void OnInventoryChanged()
		{
			UpdateVisualFromContainer();
		}

		private void OnDestroy()
		{
			((ZenMod<Plugin>)(object)ZenMod<Plugin>.Instance).HotLoad.Untrack((Object)(object)this);
		}

		protected ItemData? GetItemDataFromZDO(string itemName, int index = -1)
		{
			//IL_001a: Expected O, but got Unknown
			try
			{
				return ZdoExt.GetItemData(Nview.GetZDO(), itemName, index);
			}
			catch (MissingItemException ex)
			{
				Logging<Plugin>.Warning((object)((Exception)ex).Message, 0);
				return null;
			}
		}

		public bool IsAnyItemEquipable()
		{
			return ((VirtualInventory)this).Inventory.GetAllItems().Any((ItemData item) => item.IsEquipable());
		}

		public virtual string GetHoverName()
		{
			object obj = _inventory?.m_name;
			if (obj == null)
			{
				Piece val = default(Piece);
				if (!((Component)this).TryGetComponent<Piece>(ref val))
				{
					return GameObjectExt.GetPrefabName(((Component)this).gameObject);
				}
				obj = val.m_name;
			}
			return (string)obj;
		}

		public virtual string GetHoverText()
		{
			Sb.Clear();
			Sb.Append(GetHoverName());
			if (!WardAccessExt.CanAccessWard((MonoBehaviour)(object)this, false))
			{
				Sb.Append("\n$piece_noaccess");
			}
			else if (CanHoldToEquip())
			{
				Sb.Append("\n" + UI.PromptInteract + " $piece_use ($msg_hold_equip_hover)");
			}
			else
			{
				Sb.Append("\n" + UI.PromptInteract + " $piece_use");
			}
			return StringExt.Localize(Sb.ToString());
		}

		public void EquipItemSwap(Player player, ItemData standItem)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected I4, but got Unknown
			ItemType itemType = standItem.m_shared.m_itemType;
			ItemData val = (ItemData)((itemType - 3) switch
			{
				3 => ((Humanoid)player).m_helmetItem, 
				4 => ((Humanoid)player).m_chestItem, 
				8 => ((Humanoid)player).m_legItem, 
				14 => ((Humanoid)player).m_shoulderItem, 
				15 => ((Humanoid)player).m_utilityItem, 
				21 => ((Humanoid)player).m_trinketItem, 
				2 => ((Humanoid)player).m_leftItem ?? ((Humanoid)player).m_hiddenLeftItem, 
				1 => ((Humanoid)player).m_leftItem ?? ((Humanoid)player).m_hiddenLeftItem, 
				19 => ((Humanoid)player).m_leftItem ?? ((Humanoid)player).m_hiddenLeftItem, 
				0 => ((Humanoid)player).m_rightItem ?? ((Humanoid)player).m_hiddenRightItem, 
				11 => ((Humanoid)player).m_rightItem ?? ((Humanoid)player).m_hiddenRightItem, 
				16 => ((Humanoid)player).m_rightItem ?? ((Humanoid)player).m_hiddenRightItem, 
				17 => ((Humanoid)player).m_rightItem ?? ((Humanoid)player).m_hiddenRightItem, 
				12 => ((Humanoid)player).m_rightItem ?? ((Humanoid)player).m_hiddenRightItem, 
				_ => throw new ArgumentOutOfRangeException(), 
			});
			Inventory inventory = ((Humanoid)player).GetInventory();
			Inventory inventory2 = ((VirtualInventory)this).Inventory;
			if (val == null)
			{
				inventory.MoveItemToThis(inventory2, standItem);
			}
			else if (CanAttach(val, ignoreExisting: true) && IsSameType(standItem, val))
			{
				InventoryExt.SwapItem(inventory, val, inventory2, standItem);
			}
			((Humanoid)player).EquipItem(standItem, false);
		}

		public bool CanUseHotbarItem()
		{
			bool flag = IsInUse();
			if (Configs.EnableHotbarUseItem.Value && !flag)
			{
				return true;
			}
			if (flag)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_inuse", 0, (Sprite)null);
			}
			return false;
		}

		protected override bool IsAddItemValid(ItemData item)
		{
			if (item.m_stack == 1)
			{
				return CanAttach(item, ignoreExisting: false);
			}
			return false;
		}

		protected override bool OnSelectedItemBefore(InventoryGui __instance, InventoryGrid grid, ItemData? item, Modifier mod, Vector2i pos)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Invalid comparison between Unknown and I4
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			Inventory inventory = __instance.m_containerGrid.GetInventory();
			if (((Character)localPlayer).IsTeleporting())
			{
				return true;
			}
			if ((int)mod != 2 && (int)mod != 0)
			{
				return true;
			}
			int dragAmount = __instance.m_dragAmount;
			if ((int)mod == 0)
			{
				Inventory inventory2 = grid.GetInventory();
				Inventory dragInventory = __instance.m_dragInventory;
				ItemData dragItem = __instance.m_dragItem;
				if (dragItem == null)
				{
					return true;
				}
				if (inventory2 == dragInventory)
				{
					return true;
				}
				bool flag = false;
				ItemData itemAt = inventory2.GetItemAt(pos.x, pos.y);
				if (inventory2 == inventory)
				{
					__instance.m_dragAmount = 1;
					flag = ((itemAt == null || !Opened.IsSameType(itemAt, dragItem)) ? Opened.CanAttach(dragItem, ignoreExisting: false) : Opened.CanAttach(dragItem, ignoreExisting: true));
				}
				if (inventory2 == ((Humanoid)localPlayer).GetInventory())
				{
					if (itemAt != null)
					{
						if (ItemDataExt.GetPrefabName(dragItem) == ItemDataExt.GetPrefabName(itemAt) && ItemDataExt.IsStackable(dragItem))
						{
							return true;
						}
						flag = Opened.CanAttach(itemAt, Opened.IsSameType(dragItem, itemAt));
					}
					else
					{
						flag = true;
					}
				}
				if (flag)
				{
					if (itemAt == null)
					{
						return true;
					}
					InventoryExt.SwapItem(dragInventory, dragItem, inventory2, itemAt);
					__instance.SetupDragItem((ItemData)null, (Inventory)null, 0);
					return false;
				}
			}
			if ((int)mod == 2)
			{
				if ((Object)(object)grid == (Object)(object)__instance.ContainerGrid)
				{
					return true;
				}
				if (item != null && item.m_stack == 1)
				{
					if (Opened.CanAttach(item, ignoreExisting: false))
					{
						return true;
					}
					if (Opened.CanSwap(item, out ItemData swapItem))
					{
						InventoryExt.SwapItem(grid.GetInventory(), item, inventory, swapItem);
						return false;
					}
				}
			}
			__instance.m_dragAmount = dragAmount;
			Opened.ShowErrorMessage();
			return false;
		}
	}
	internal class ItemStandInventory : StandInventory
	{
		private ItemStand _stand;

		private static readonly StringBuilder Sb = new StringBuilder();

		protected override void Awake()
		{
			if (!((Component)this).TryGetComponent<ItemStand>(ref _stand))
			{
				throw new Exception("ItemStand component not found on " + ((Object)this).name);
			}
			SetupInventory(_stand.m_name, 1, 1);
			base.Awake();
		}

		public override void ShowErrorMessage()
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, "$piece_itemstand_cantattach", 0, (Sprite)null);
		}

		protected override bool IsSameType(ItemData standItem, ItemData compareItem)
		{
			if (compareItem.m_stack > 1)
			{
				return false;
			}
			if (_stand.CanAttach(standItem))
			{
				return _stand.CanAttach(compareItem);
			}
			return false;
		}

		protected override bool CanAttach(ItemData itemData, bool ignoreExisting)
		{
			if (!ignoreExisting)
			{
				if (_stand.CanAttach(itemData))
				{
					return ((VirtualInventory)this).Inventory.NrOfItems() == 0;
				}
				return false;
			}
			return _stand.CanAttach(itemData);
		}

		protected override bool CanSwap(ItemData externItem, out ItemData swapItem)
		{
			ItemData val = (swapItem = GetMountedItem());
			if (val != null && IsSameType(val, externItem))
			{
				return true;
			}
			return false;
		}

		public override void SwapEquip()
		{
			ItemData mountedItem = GetMountedItem();
			if (mountedItem != null)
			{
				if (!mountedItem.IsEquipable())
				{
					Logging<Plugin>.Info("Item stand item is not equipable, aborting swap.", 0);
				}
				else
				{
					EquipItemSwap(Player.m_localPlayer, mountedItem);
				}
			}
		}

		private ItemData? GetMountedItem()
		{
			if (((VirtualInventory)this).Inventory.NrOfItems() <= 0)
			{
				return GetAttachedItemFromZDO();
			}
			return ((VirtualInventory)this).Inventory.GetItem(0);
		}

		private bool AttachItem(ItemData item)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if (!_stand.CanAttach(item))
			{
				return false;
			}
			if (!base.Nview.IsValid())
			{
				return false;
			}
			base.Nview.ClaimOwnership();
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(16, 1, ref flag);
			if (flag)
			{
				val.AppendLiteral("Attaching item: ");
				val.AppendFormatted(ItemDataExt.GetPrefabName(item));
			}
			Logging<Plugin>.Info(val, 0);
			ZDO zDO = base.Nview.GetZDO();
			zDO.Set(ZDOVars.s_item, ItemDataExt.GetPrefabName(item));
			ItemDrop.SaveToZDO(item, zDO);
			return true;
		}

		private ItemData? GetAttachedItemFromZDO()
		{
			return GetItemDataFromZDO(_stand.GetAttachedItem());
		}

		protected override bool IsStandInventoryDiff()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			if (((VirtualInventory)this).Inventory.NrOfItems() == 0)
			{
				return _stand.HaveAttachment();
			}
			if (!_stand.HaveAttachment())
			{
				return true;
			}
			ItemData attachedItemFromZDO = GetAttachedItemFromZDO();
			int num;
			if (attachedItemFromZDO == null)
			{
				num = 0;
			}
			else
			{
				num = ((!ItemDataExt.IsEqual(attachedItemFromZDO, ((VirtualInventory)this).Inventory.GetItem(0))) ? 1 : 0);
				if (num != 0)
				{
					goto IL_008a;
				}
			}
			bool flag = default(bool);
			InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(35, 1, ref flag);
			if (flag)
			{
				val.AppendLiteral("Container and stand are identical: ");
				val.AppendFormatted(((attachedItemFromZDO != null) ? ItemDataExt.GetName(attachedItemFromZDO) : null) ?? "No Item");
			}
			Logging<Plugin>.Debug(val, 0);
			goto IL_008a;
			IL_008a:
			return (byte)num != 0;
		}

		protected override void LoadInventory()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			Logging<Plugin>.Info("Fill inventory from item stand", 0);
			ItemData attachedItemFromZDO = GetAttachedItemFromZDO();
			if (attachedItemFromZDO != null)
			{
				((VirtualInventory)this).Inventory.AddItem(attachedItemFromZDO);
				bool flag = default(bool);
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(40, 1, ref flag);
				if (flag)
				{
					val.AppendLiteral("Added item to container from ItemStand: ");
					val.AppendFormatted(ItemDataExt.GetName(attachedItemFromZDO));
				}
				Logging<Plugin>.Info(val, 0);
			}
		}

		protected override void UpdateVisualFromContainer()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			if (!IsStandInventoryDiff())
			{
				return;
			}
			Logging<Plugin>.Info("Updating visuals data", 0);
			ClearItemStand();
			ItemData mountedItem = GetMountedItem();
			if (mountedItem == null || AttachItem(mountedItem))
			{
				UpdateVisualEveryone();
				Transform transform = ((Component)this).transform;
				_stand.m_effects.Create(transform.position, transform.rotation, (Transform)null, 1f, -1);
				bool flag = default(bool);
				InterpolatedString<Plugin> val = new InterpolatedString<Plugin>(32, 2, ref flag);
				if (flag)
				{
					val.AppendFormatted("ItemStand");
					val.AppendLiteral(" updated visual from container: ");
					val.AppendFormatted((mountedItem != null) ? ItemDataExt.GetPrefabName(mountedItem) : null);
				}
				Logging<Plugin>.Info(val, 0);
			}
			void ClearItemStand()
			{
				base.Nview.ClaimOwnership();
				base.Nview.GetZDO().Set(ZDOVars.s_item, string.Empty);
				_stand.SetVisualItem(string.Empty, 0, 0, 0);
			}
		}

		private void UpdateVisualEveryone()
		{
			ZDO zDO = base.Nview.GetZDO();
			string text = zDO.GetString(ZDOVars.s_item, "");
			int num = zDO.GetInt(ZDOVars.s_variant, 0);
			int num2 = zDO.GetInt(ZDOVars.s_quality, 0);
			base.Nview.InvokeRPC(ZNetView.Everybody, "SetVisualItem", new object[4]
			{
				string.Empty,
				0,
				0,
				0
			});
			base.Nview.InvokeRPC(ZNetView.Everybody, "SetVisualItem", new object[4]
			{
				text,
				num,
				num2,
				_stand.GetOrientation()
			});
		}

		protected override bool IsStackAllButtonVisible()
		{
			if (Configs.EnableItemStandEquipButton.Value && !Conflict.IsConflict)
			{
				return base.IsStackAllButtonVisible();
			}
			return false;
		}

		protected override bool CanHoldToEquip()
		{
			return false;
		}

		public override string GetHoverText()
		{
			Sb.Clear();
			Sb.Append(base.GetHoverText());
			if (WardAccessExt.CanAccessWard((MonoBehaviour)(object)this, false) && _stand.HasOrientations() && _stand.HaveAttachment())
			{
				Sb.Append(StringExt.Localize("\n" + UI.PromptInteractAlt + " $hud_changeorientation"));
			}
			if (!Plugin.IsZenHoverItemInstalled && Configs.ShowItemOnStandName.Value)
			{
				ItemData? mountedItem = GetMountedItem();
				string text = ((mountedItem != null) ? StringExt.Localize(ItemDataExt.GetName(mountedItem)) : null);
				if (!Utility.IsNullOrWhiteSpace(text))
				{
					Sb.Append($"\n<color={UIColor.MinorInfo}>{text}</color>");
				}
			}
			return Sb.ToString();
		}
	}
	[HarmonyPatch]
	internal static class ItemStandPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(ItemStand), "GetHoverText")]
		private static void ItemStand_GetHoverText(ItemStand __instance, ref string __result)
		{
			if (((MonoBehaviour)(object)__instance).HasStandInventory(out StandInventory si))
			{
				__result = si.GetHoverText();
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ItemStand), "UseItem")]
		private static void ItemStand_UseItem(ItemStand __instance, ref bool __runOriginal, ref bool __result)
		{
			if (((MonoBehaviour)(object)__instance).HasStandInventory(out StandInventory si) && !si.CanUseHotbarItem())
			{
				__runOriginal = false;
				__result = false;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ItemStand), "Interact")]
		private static void ItemStand_Interact(ItemStand __instance, Humanoid user, bool alt, bool hold, ref bool __result, ref bool __runOriginal)
		{
			if (((MonoBehaviour)(object)__instance).HasStandInventory(out StandInventory si) && !alt)
			{
				__runOriginal = false;
				if (!hold)
				{
					__result = true;
					si.Open();
					Game.instance.IncrementPlayerStat((PlayerStatType)24, 1f);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ItemStand), "SetVisualItem")]
		private static void ItemStand_SetVisualItem(ItemStand __instance, string itemName, int variant)
		{
			if (__instance.m_visualName != itemName || __instance.m_visualVariant != variant)
			{
				Object.Destroy((Object)(object)__instance.m_visualItem);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ItemStand), "RPC_DropItem")]
		private static void ItemStand_RPC_DropItem(ItemStand __instance)
		{
			if (((MonoBehaviour)(object)__instance).IsThisStandOpen())
			{
				InventoryGui.instance.Hide();
			}
		}
	}
	[Disable(new Type[] { typeof(StandInventory) })]
	[BepInPlugin("ZenDragon.ZenItemStands", "ZenItemStands", "1.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class Plugin : ZenMod<Plugin>
	{
		public const string PluginName = "ZenItemStands";

		public const string PluginVersion = "1.0.2";

		public const string PluginGUID = "ZenDragon.ZenItemStands";

		public static bool IsZenHoverItemInstalled => Chainloader.PluginInfos.ContainsKey("ZenDragon.ZenHoverItem");

		protected override void Setup()
		{
			base.LanguageChanged += UpdateTranslations;
			base.HotLoad.PrefabInit += Startup.InitPrefabs;
			Conflict.Verify();
		}

		protected override void TitleScene(bool isFirstBoot)
		{
		}

		protected override void WorldStart()
		{
		}

		protected override void Shutdown()
		{
		}

		protected override void HotRestore()
		{
			IEnumerable<GameObject> first = from stand in Object.FindObjectsByType<ItemStand>((FindObjectsSortMode)0)
				select ((Component)stand).gameObject;
			IEnumerable<GameObject> second = from stand in Object.FindObjectsByType<ArmorStand>((FindObjectsSortMode)0)
				select ((Component)stand).gameObject;
			Startup.Init(from obj in first.Concat(second)
				where ((IEnumerable<string>)Configs.StandPrefabNames.Value).Any((string prefabName) => prefabName == Utils.GetPrefabName(((Object)obj).name))
				select obj);
		}

		private static void UpdateTranslations(string language)
		{
			if (Configs.EnableArmorStandAmericanSpelling.Value && language == "English")
			{
				Localization.instance.m_translations["piece_armorstand"] = "Armor Stand";
			}
		}
	}
}
namespace ZenItemStands.Compatibility
{
	internal static class Conflict
	{
		private static readonly string[] ConflictedMods = new string[3] { "aedenthorn.ExtendedPlayerInventory", "randyknapp.mods.equipmentandquickslots", "com.bruce.valheim.comfyquickslots" };

		internal static bool IsConflict { get; private set; }

		internal static void Verify()
		{
			if (ConflictedMods.Any((string modID) => Chainloader.PluginInfos.ContainsKey(modID)))
			{
				IsConflict = true;
				Logging<Plugin>.Message((object)("ZenItemStands: The Use/Equip quick swap functionality will be disabled.\r\nThis is to protect against item duplication due to one of the following mods being installed:\r\n" + GeneralExtensions.Join<string>((IEnumerable<string>)ConflictedMods, (Func<string, string>)null, "\n")), 0);
			}
		}
	}
}