Decompiled source of ZenItemStands v0.5.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 BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;
using Zen.Compatibility;
using Zen.Config;
using Zen.Lib;
using Zen.Logging;

[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]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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
{
	public class ArmorStandContainer : StandContainer
	{
		internal ArmorStand Stand;

		protected override void Awake()
		{
			if (!Object.op_Implicit((Object)(object)Stand) && !((Component)this).TryGetComponent<ArmorStand>(ref Stand))
			{
				throw new Exception("ArmorStand component not found on " + ((Object)this).name);
			}
			((Container)this).m_name = Stand.m_name;
			((Container)this).m_width = Stand.m_slots.Count;
			((Container)this).m_height = 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);
		}

		public 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)
		{
			ItemData item2 = item;
			return ((IEnumerable<ArmorStandSlot>)Stand.m_slots).FirstOrDefault((Func<ArmorStandSlot, bool>)((ArmorStandSlot slot) => slot.m_currentItemName == ItemDataExt.GetName(item2)));
		}

		private ItemData? GetAttachedItemData(int index)
		{
			string attachedItem = Stand.GetAttachedItem(index);
			Log.Debug((object)$"Index: {index} Item: {attachedItem}", (ushort)0);
			return GetItemData(attachedItem, index);
		}

		protected override bool IsStandInventoryDiff()
		{
			int num = 0;
			for (int i = 0; i < Stand.m_slots.Count; i++)
			{
				ItemData attachedItemData = GetAttachedItemData(i);
				if (attachedItemData != null)
				{
					if (!ItemDataExt.HaveItemData(((Container)this).m_inventory, attachedItemData))
					{
						Log.Info((object)("Diff Item: " + ItemDataExt.GetName(attachedItemData)), (ushort)0);
						return true;
					}
					num++;
				}
			}
			bool num2 = num != ((Container)this).m_inventory.NrOfItems();
			if (!num2)
			{
				Log.Debug((object)$"Container and stand are identical: {num} items", (ushort)0);
			}
			return num2;
		}

		public 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)
		{
			ItemData item2 = item;
			index = -1;
			for (int i = 0; i < Stand.m_slots.Count; i++)
			{
				if (CanAttachAt(i))
				{
					index = i;
					return true;
				}
			}
			return false;
			bool CanAttachAt(int index)
			{
				//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[index];
				if (!Stand.CanAttach(val, item2))
				{
					return false;
				}
				if (!ignoreExisting && Stand.HaveAttachment(index))
				{
					return false;
				}
				ItemType itemType = item2.m_shared.m_itemType;
				if (((int)itemType == 7 || (int)itemType == 11) ? true : false)
				{
					return true;
				}
				foreach (Transform item3 in item2.m_dropPrefab.transform)
				{
					if (((Object)item3).name.StartsWith("attach"))
					{
						return true;
					}
				}
				return false;
			}
		}

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

		public override void SwapEquip()
		{
			Inventory inventory = ((Container)this).m_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)
			{
				((Humanoid)(object)localPlayer).EquipContainerStandItem(standItem);
			}
			((Humanoid)localPlayer).HideHandItems(false, true);
			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;
			}
			if (((Container)this).m_nview.IsOwner())
			{
				ZDO zDO = ((Container)this).m_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)
			if (IsStandInventoryDiff())
			{
				Log.Info((object)"Updating visuals and slot data", (ushort)0);
				ClearArmorStand();
				int num = ((Container)this).m_inventory.GetAllItems().Count(AttachItem);
				Stand.UpdateVisual();
				Transform transform = ((Component)this).transform;
				Stand.m_effects.Create(transform.position, transform.rotation, (Transform)null, 1f, -1);
				Log.Info((object)string.Format("{0} loaded {1} items from container", "ArmorStand", num), (ushort)0);
			}
			void ClearArmorStand()
			{
				for (int i = 0; i < Stand.m_slots.Count; i++)
				{
					Stand.SetVisualItem(i, string.Empty, 0);
					if (((Container)this).m_nview.IsOwner())
					{
						((Container)this).m_nview.GetZDO().Set(i + "_item", string.Empty);
					}
				}
				Stand.UpdateSupports();
			}
		}

		protected override bool FillContainer()
		{
			Log.Info((object)"Fill inventory from slots", (ushort)0);
			((Container)this).m_inventory.RemoveAll();
			for (int i = 0; i < Stand.m_slots.Count; i++)
			{
				if (Stand.HaveAttachment(i))
				{
					ItemData attachedItemData = GetAttachedItemData(i);
					if (attachedItemData != null)
					{
						((Container)this).m_inventory.AddItem(attachedItemData);
						Log.Info((object)("Added item to container from ArmorStand slot: " + ItemDataExt.GetName(attachedItemData)), (ushort)0);
					}
				}
			}
			return true;
		}

		public override void ShowHideStackAllButton()
		{
			InventoryGuiExt.ShowStackAllButton(InventoryGui.instance, true);
		}
	}
	public static class ArmorStandExt
	{
		public static void UpdateContainer(this ArmorStand armorStand)
		{
			StandContainer.UpdateContainer(((Component)armorStand).gameObject);
		}

		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]
	public 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)
			{
				__instance.UpdateSupports();
				Log.Info((object)string.Format("{0} index: {1}", "SetPose", __instance.m_pose), (ushort)0);
			}
		}

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

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Switch), "GetHoverText")]
		private static void ArmorStand_Switch_GetHoverText(Switch __instance, ref string __result)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			ArmorStand componentInParent = ((Component)__instance).GetComponentInParent<ArmorStand>();
			if (Object.op_Implicit((Object)(object)componentInParent) && componentInParent.HasContainer(out ArmorStandContainer c))
			{
				__result = StandUI.GetHoverText(c);
				if (WardAccessExt.CanAccessWard(((Component)__instance).transform.position, false) && Configs.EnableArmorStandPoseChange.Value && componentInParent.HasChestAndLegItem())
				{
					__result += Localization.instance.Localize("\n" + UI.PromptInteractAlt + " Change pose");
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ArmorStand), "UpdateSupports")]
		private static void ArmorStand_UpdateSupports(ArmorStand __instance)
		{
			if (!Configs.EnableArmorStandPoseChange.Value)
			{
				return;
			}
			if (__instance.m_supports.Count == 0)
			{
				Log.Warning((object)"m_supports is length 0 when it should be at least 1, aborting.", (ushort)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) && componentInParent.HasContainer(out ArmorStandContainer c))
			{
				__runOriginal = false;
				if (alt && !hold && Configs.EnableArmorStandPoseChange.Value)
				{
					componentInParent.NextPose();
					__result = true;
				}
				else
				{
					__result = StandUI.Open(c, character, hold);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ArmorStand), "UseItem")]
		private static void ArmorStand_UseItem(ArmorStand __instance, ref bool __result, ref bool __runOriginal)
		{
			if (__instance.HasContainer(out ArmorStandContainer c) && !StandUI.CanUseHotbarItem(((Container)c).IsInUse()))
			{
				__runOriginal = false;
				__result = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ArmorStand), "RPC_DropItemByName")]
		private static void ArmorStand_RPC_DropItemByName(ArmorStand __instance)
		{
			if (__instance.IsOpenContainer())
			{
				InventoryGui.instance.Hide();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ArmorStand), "UpdateVisual")]
		private static void ArmorStand_UpdateVisual(ArmorStand __instance)
		{
			__instance.UpdateContainer();
		}
	}
	public 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> EnableArmorStandAmericanSpelling;

		private const string SECTION_ITEMSTAND = "Piece: ItemStand";

		public static readonly ConfigEntry<bool> EnableItemStandHoldToEquip;

		static Configs()
		{
			//IL_0010: 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_0020: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0040: Expected O, but got Unknown
			StringList val = new StringList(Array.Empty<IEnumerable<string>>());
			((List<string>)val).Add("itemstand");
			((List<string>)val).Add("itemstandh");
			((List<string>)val).Add("ArmorStand");
			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 chaging 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?");
			EnableArmorStandAmericanSpelling = Config.Define<bool>(false, "Piece: ArmorStand", "American Spelling", true, "Change the spelling to 'Armor Stand' instead of 'Armour Stand'");
			EnableItemStandHoldToEquip = Config.Define<bool>(true, "Piece: ItemStand", "Enable Hold To Equip", false, "Should (Hold to equip) be available on Item Stands hover text?");
		}
	}
	public static class ItemStandExt
	{
		public static void UpdateContainer(this ItemStand itemStand)
		{
			StandContainer.UpdateContainer(((Component)itemStand).gameObject);
		}
	}
	public static class Startup
	{
		public static List<StandContainer> InitPrefabs()
		{
			Log.Info((object)"Initializing", (ushort)0);
			List<StandContainer> containers = new List<StandContainer>();
			foreach (string item in (List<string>)(object)Configs.StandPrefabNames.Value)
			{
				if (!InitPrefab<ArmorStand>(item) && !InitPrefab<ItemStand>(item))
				{
					Log.Error((object)("Prefab is not ArmorStand or ItemStand: " + item), (ushort)0);
				}
			}
			return containers;
			bool InitPrefab<T>(string prefabName) where T : notnull, Component
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
				if (!Object.op_Implicit((Object)(object)prefab))
				{
					throw new Exception("Prefab not found: " + prefabName);
				}
				T component = prefab.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()}");
					}
					containers.Add(AddContainer<ItemStandContainer>(prefab));
				}
				else
				{
					containers.Add(AddContainer<ArmorStandContainer>(prefab));
				}
				return true;
			}
		}

		public static T AddContainer<T>(GameObject targetObject) where T : StandContainer
		{
			T result = default(T);
			if (targetObject.TryGetComponent<T>(ref result))
			{
				return result;
			}
			result = targetObject.AddComponent<T>();
			((Container)result).m_checkGuardStone = true;
			return result;
		}
	}
	[HarmonyPatch(typeof(Container))]
	internal static class StandContainerPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("DropAllItems", new Type[] { })]
		private static void DropAllItems(Container __instance, ref bool __runOriginal)
		{
			if (__instance is StandContainer)
			{
				__instance.GetInventory().RemoveAll();
				__runOriginal = false;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("Save")]
		private static void Save(Container __instance, ref bool __runOriginal)
		{
			if (__instance is StandContainer standContainer)
			{
				Log.Info((object)$"NON-PERSISTANT: {((object)standContainer).GetType()}", (ushort)0);
				__runOriginal = false;
			}
		}
	}
	public static class StandContainerExt
	{
		public static bool HasContainer(this ArmorStand s, out ArmorStandContainer c)
		{
			return ((Component)s).TryGetComponent<ArmorStandContainer>(ref c);
		}

		public static bool HasContainer(this ItemStand s, out ItemStandContainer c)
		{
			return ((Component)s).TryGetComponent<ItemStandContainer>(ref c);
		}

		public static bool HasContainerStand(this GameObject g, out StandContainer c)
		{
			return g.TryGetComponent<StandContainer>(ref c);
		}
	}
	public static class StandUI
	{
		private static StandContainer? _opened;

		private static float _closeTime;

		public static bool IsOpen => Object.op_Implicit((Object)(object)_opened);

		public static bool IsRecentlyClosed => Time.time < _closeTime + 0.5f;

		public static StandContainer Opened
		{
			get
			{
				if (!IsOpen)
				{
					throw new Exception("Can not access container, not open");
				}
				return _opened;
			}
		}

		private static bool IsOpenContainer(GameObject g)
		{
			if (g.HasContainerStand(out StandContainer c))
			{
				return c.IsOpen;
			}
			return false;
		}

		public static bool IsOpenContainer(this ItemStand s)
		{
			return IsOpenContainer(((Component)s).gameObject);
		}

		public static bool IsOpenContainer(this ArmorStand s)
		{
			return IsOpenContainer(((Component)s).gameObject);
		}

		internal static void Translations(string language)
		{
			if (Configs.EnableArmorStandAmericanSpelling.Value && language == "English")
			{
				Localization.instance.m_translations["piece_armorstand"] = "Armor Stand";
			}
		}

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

		public static bool Open(StandContainer container, Humanoid user, bool hold)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if (IsOpen || IsRecentlyClosed)
			{
				InventoryGui.instance.Hide();
				return false;
			}
			if (!ZenMod<Plugin>.IsOnServerAndAllClients)
			{
				((Container)container).m_nview.ClaimOwnership();
			}
			if (!((Container)container).Interact(user, hold, false))
			{
				return false;
			}
			_opened = container;
			_opened.ShowHideStackAllButton();
			Log.Info((object)$"Opened Stand: {((object)_opened).GetType()}", (ushort)0);
			Game instance = Game.instance;
			PlayerStatType val;
			if (!(container is ArmorStandContainer))
			{
				if (!(container is ItemStandContainer))
				{
					throw new Exception($"Invalid type of stand: {((object)container).GetType()}");
				}
				val = (PlayerStatType)24;
			}
			else
			{
				val = (PlayerStatType)25;
			}
			instance.IncrementPlayerStat(val, 1f);
			return true;
		}

		public static void OnShowUI(InventoryGui gui, StandContainer? container)
		{
			container?.TryFill();
			InventoryGridExt.ShowAmountText(gui.ContainerGrid, false, -1);
		}

		public static void OnHideUI(InventoryGui gui)
		{
			InventoryGui gui2 = gui;
			if (_opened is ArmorStandContainer armorStandContainer && Configs.EnableArmorStandPoseChange.Value && !armorStandContainer.Stand.HasChestAndLegItem())
			{
				armorStandContainer.Stand.ResetPose();
			}
			Timing.WhenNot((Func<bool>)InventoryGui.IsVisible, (Action)delegate
			{
				Timing.Delay(0.5f, (Action)delegate
				{
					InventoryGridExt.ShowAmountText(gui2.ContainerGrid, true, -1);
				});
			});
			Close();
		}

		private static void Close()
		{
			if (IsOpen)
			{
				_closeTime = Time.time;
				_opened = null;
			}
		}

		public static bool CanSwap(ItemData item, out ItemData swapItem)
		{
			swapItem = null;
			if (Object.op_Implicit((Object)(object)_opened))
			{
				return _opened.CanSwap(item, out swapItem);
			}
			return false;
		}

		public static void SwapEquip(bool isButtonPressed)
		{
			Log.Info((object)"Swap equipment", (ushort)0);
			StandContainer opened = _opened;
			if (!(opened is ArmorStandContainer))
			{
				if (opened is ItemStandContainer && (isButtonPressed || Configs.EnableItemStandHoldToEquip.Value))
				{
					_opened.SwapEquip();
				}
			}
			else if (isButtonPressed || Configs.EnableArmorStandHoldToEquip.Value)
			{
				_opened.SwapEquip();
			}
		}

		public static void EquipContainerStandItem(this Humanoid 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_0066: Expected I4, but got Unknown
			ItemType itemType = standItem.m_shared.m_itemType;
			ItemData val = (ItemData)((itemType - 3) switch
			{
				3 => player.m_helmetItem, 
				4 => player.m_chestItem, 
				8 => player.m_legItem, 
				14 => player.m_shoulderItem, 
				15 => player.m_utilityItem, 
				2 => player.m_leftItem ?? player.m_hiddenLeftItem, 
				1 => player.m_leftItem ?? player.m_hiddenLeftItem, 
				19 => player.m_leftItem ?? player.m_hiddenLeftItem, 
				0 => player.m_rightItem ?? player.m_hiddenRightItem, 
				11 => player.m_rightItem ?? player.m_hiddenRightItem, 
				16 => player.m_rightItem ?? player.m_hiddenRightItem, 
				17 => player.m_rightItem ?? player.m_hiddenRightItem, 
				12 => player.m_rightItem ?? player.m_hiddenRightItem, 
				_ => throw new ArgumentOutOfRangeException(), 
			});
			Inventory inventory = player.GetInventory();
			Inventory inventory2 = ((Container)Opened).GetInventory();
			if (val == null)
			{
				inventory.MoveItemToThis(inventory2, standItem);
			}
			else if (Opened.CanAttach(val, ignoreExisting: true) && Opened.IsSameType(standItem, val))
			{
				ItemDataExt.SwapItem(inventory, val, inventory2, standItem);
			}
			player.EquipItem(standItem, false);
		}

		private static bool CanHoldToEquip(StandContainer stand)
		{
			if (!(stand is ArmorStandContainer))
			{
				if (stand is ItemStandContainer)
				{
					if (Configs.EnableItemStandHoldToEquip.Value)
					{
						return stand.IsAnyItemEquipable();
					}
					return false;
				}
				throw new Exception($"Unknown stand type: {((object)stand).GetType()}");
			}
			return Configs.EnableArmorStandHoldToEquip.Value;
		}

		public static string GetHoverText(StandContainer container)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			string hoverName = ((Container)container).GetHoverName();
			hoverName = ((!WardAccessExt.CanAccessWard(((Component)container).transform.position, false)) ? (hoverName + "\n$piece_noaccess") : ((!CanHoldToEquip(container)) ? (hoverName + "\n" + UI.PromptInteract + " $piece_use") : (hoverName + "\n" + UI.PromptInteract + " $piece_use (Hold to equip)")));
			return Localization.instance.Localize(hoverName);
		}
	}
	[HarmonyPatch]
	internal static class StandUIPatch
	{
		[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")]
			private static void Inventory_StackAll(ref bool __runOriginal)
			{
				if (StandUI.IsOpen)
				{
					StandUI.SwapEquip(_isButtonPressed);
					__runOriginal = false;
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
		private static void InventoryGrid_DropItem(InventoryGrid __instance, Inventory fromInventory, ref int amount)
		{
			if (StandUI.IsOpen && __instance.GetInventory() != fromInventory && __instance.GetInventory() == InventoryGui.instance.ContainerGrid.GetInventory())
			{
				amount = 1;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")]
		private static void InventoryGui_OnSelectedItem(InventoryGui __instance, InventoryGrid grid, ItemData item, Modifier mod, Vector2i pos, ref bool __runOriginal)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Invalid comparison between Unknown and I4
			//IL_0047: 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)
			if (!StandUI.IsOpen)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (((Character)localPlayer).IsTeleporting() || ((int)mod != 2 && (int)mod != 0))
			{
				return;
			}
			if ((int)mod == 0)
			{
				Inventory inventory = grid.GetInventory();
				Inventory dragInventory = __instance.m_dragInventory;
				ItemData dragItem = __instance.m_dragItem;
				if (dragItem == null || inventory == dragInventory)
				{
					return;
				}
				bool flag = false;
				ItemData itemAt = inventory.GetItemAt(pos.x, pos.y);
				if (inventory == ((Container)StandUI.Opened).GetInventory())
				{
					flag = ((itemAt == null || !StandUI.Opened.IsSameType(itemAt, dragItem)) ? StandUI.Opened.CanAttach(dragItem, ignoreExisting: false) : StandUI.Opened.CanAttach(dragItem, ignoreExisting: true));
				}
				if (inventory == ((Humanoid)localPlayer).GetInventory())
				{
					flag = itemAt == null || StandUI.Opened.CanAttach(itemAt, StandUI.Opened.IsSameType(dragItem, itemAt));
				}
				if (flag)
				{
					if (itemAt != null)
					{
						ItemDataExt.SwapItem(dragInventory, dragItem, inventory, itemAt);
						__instance.SetupDragItem((ItemData)null, (Inventory)null, 0);
						__runOriginal = false;
					}
					return;
				}
			}
			if ((int)mod == 2)
			{
				if ((Object)(object)grid == (Object)(object)__instance.ContainerGrid || StandUI.Opened.CanAttach(item, ignoreExisting: false))
				{
					return;
				}
				if (StandUI.CanSwap(item, out ItemData swapItem))
				{
					ItemDataExt.SwapItem(grid.GetInventory(), item, ((Container)StandUI.Opened).GetInventory(), swapItem);
					__runOriginal = false;
					return;
				}
			}
			StandUI.Opened.ShowErrorMessage();
			__runOriginal = false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryGui), "Show")]
		private static void InventoryGui_Show(InventoryGui __instance, Container? container)
		{
			if (container is StandContainer container2)
			{
				StandUI.OnShowUI(__instance, container2);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryGui), "Hide")]
		private static void InventoryGui_Hide(InventoryGui __instance)
		{
			if (StandUI.IsOpen)
			{
				StandUI.OnHideUI(__instance);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Localization), "Localize", new Type[] { typeof(string) })]
		private static void Localization_Localize(ref string text)
		{
			if (StandUI.IsOpen || StandUI.IsRecentlyClosed)
			{
				text = text.Replace("$inventory_stackall", "$inventory_use");
			}
		}
	}
	public class ItemStandContainer : StandContainer
	{
		internal ItemStand Stand;

		protected override void Awake()
		{
			if (!Object.op_Implicit((Object)(object)Stand) && !((Component)this).TryGetComponent<ItemStand>(ref Stand))
			{
				throw new Exception("ItemStand component not found on " + ((Object)this).name);
			}
			((Container)this).m_width = 1;
			((Container)this).m_height = 1;
			((Container)this).m_name = Stand.m_name;
			base.Awake();
		}

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

		public override bool IsSameType(ItemData standItem, ItemData compareItem)
		{
			if (Stand.CanAttach(standItem))
			{
				return Stand.CanAttach(compareItem);
			}
			return false;
		}

		public override bool CanAttach(ItemData itemData, bool ignoreExisting)
		{
			if (!ignoreExisting)
			{
				if (Stand.CanAttach(itemData))
				{
					return ((Container)this).m_inventory.NrOfItems() == 0;
				}
				return false;
			}
			return Stand.CanAttach(itemData);
		}

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

		public override void SwapEquip()
		{
			ItemData containerItem = GetContainerItem();
			if (containerItem != null)
			{
				if (!containerItem.IsEquipable())
				{
					Log.Info((object)"Item stand item is not equipable, aborting swap.", (ushort)0);
				}
				else
				{
					((Humanoid)(object)Player.m_localPlayer).EquipContainerStandItem(containerItem);
				}
			}
		}

		private ItemData? GetContainerItem()
		{
			if (((Container)this).m_inventory.NrOfItems() <= 0)
			{
				return null;
			}
			return ((Container)this).m_inventory.GetItem(0);
		}

		private bool AttachItem(ItemData item)
		{
			if (!Stand.CanAttach(item))
			{
				return false;
			}
			if (((Container)this).m_nview.IsOwner())
			{
				Log.Info((object)("Attaching item: " + ItemDataExt.GetPrefabName(item)), (ushort)0);
				ZDO zDO = ((Container)this).m_nview.GetZDO();
				zDO.Set(ZDOVars.s_item, ItemDataExt.GetPrefabName(item));
				ItemDrop.SaveToZDO(item, zDO);
			}
			return true;
		}

		private ItemData? GetAttachedItemData()
		{
			string attachedItem = Stand.GetAttachedItem();
			return GetItemData(attachedItem);
		}

		protected override bool IsStandInventoryDiff()
		{
			if (((Container)this).m_inventory.NrOfItems() == 0)
			{
				return Stand.HaveAttachment();
			}
			if (!Stand.HaveAttachment())
			{
				return true;
			}
			ItemData attachedItemData = GetAttachedItemData();
			int num;
			if (attachedItemData == null)
			{
				num = 0;
			}
			else
			{
				num = ((!ItemDataExt.IsEqual(attachedItemData, ((Container)this).m_inventory.GetItem(0))) ? 1 : 0);
				if (num != 0)
				{
					goto IL_0072;
				}
			}
			Log.Debug((object)("Container and stand are identical: " + (((attachedItemData != null) ? ItemDataExt.GetName(attachedItemData) : null) ?? "No Item")), (ushort)0);
			goto IL_0072;
			IL_0072:
			return (byte)num != 0;
		}

		protected override bool FillContainer()
		{
			Log.Info((object)"Fill inventory from item stand", (ushort)0);
			((Container)this).m_inventory.RemoveAll();
			ItemData attachedItemData = GetAttachedItemData();
			if (attachedItemData == null)
			{
				return false;
			}
			((Container)this).m_inventory.AddItem(attachedItemData);
			Log.Info((object)("Added item to container from ItemStand: " + ItemDataExt.GetName(attachedItemData)), (ushort)0);
			return true;
		}

		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)
			if (IsStandInventoryDiff())
			{
				Log.Info((object)"Updating visuals data", (ushort)0);
				ClearItemStand();
				ItemData containerItem = GetContainerItem();
				if (containerItem == null || AttachItem(containerItem))
				{
					UpdateVisualEveryone();
					Transform transform = ((Component)this).transform;
					Stand.m_effects.Create(transform.position, transform.rotation, (Transform)null, 1f, -1);
					Log.Info((object)("ItemStand updated visual from container: " + ((containerItem != null) ? ItemDataExt.GetPrefabName(containerItem) : null)), (ushort)0);
				}
			}
			void ClearItemStand()
			{
				Stand.SetVisualItem(string.Empty, 0, 0);
				if (((Container)this).m_nview.IsOwner())
				{
					((Container)this).m_nview.GetZDO().Set(ZDOVars.s_item, string.Empty);
				}
			}
		}

		private void UpdateVisualEveryone()
		{
			ZDO zDO = ((Container)this).m_nview.GetZDO();
			string @string = zDO.GetString(ZDOVars.s_item, "");
			int @int = zDO.GetInt(ZDOVars.s_variant, 0);
			int int2 = zDO.GetInt(ZDOVars.s_quality, 0);
			((Container)this).m_nview.InvokeRPC(ZNetView.Everybody, "SetVisualItem", new object[3]
			{
				string.Empty,
				0,
				0
			});
			((Container)this).m_nview.InvokeRPC(ZNetView.Everybody, "SetVisualItem", new object[3] { @string, @int, int2 });
		}
	}
	[HarmonyPatch]
	public static class ItemStandPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(ItemStand), "GetHoverText")]
		private static void ItemStand_GetHoverText(ItemStand __instance, ref string __result)
		{
			if (__instance.HasContainer(out ItemStandContainer c))
			{
				__result = StandUI.GetHoverText(c);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ItemStand), "UseItem")]
		private static void ItemStand_UseItem(ItemStand __instance, ref bool __runOriginal, ref bool __result)
		{
			if (__instance.HasContainer(out ItemStandContainer c) && !StandUI.CanUseHotbarItem(((Container)c).IsInUse()))
			{
				__runOriginal = false;
				__result = false;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ItemStand), "Interact")]
		private static void ItemStand_Interact(ItemStand __instance, Humanoid user, bool hold, ref bool __result, ref bool __runOriginal)
		{
			if (__instance.HasContainer(out ItemStandContainer c))
			{
				__result = StandUI.Open(c, user, hold);
				__runOriginal = false;
			}
		}

		[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 (__instance.IsOpenContainer())
			{
				InventoryGui.instance.Hide();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ItemStand), "UpdateVisual")]
		private static void ItemStand_UpdateVisual(ItemStand __instance)
		{
			__instance.UpdateContainer();
		}
	}
	[Disable(new Type[] { typeof(StandContainer) })]
	[BepInPlugin("ZenDragon.ZenItemStands", "ZenItemStands", "0.5.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 = "0.5.2";

		public const string PluginGUID = "ZenDragon.ZenItemStands";

		protected override void Setup()
		{
			((ZenMod)this).LanguageChanged += StandUI.Translations;
			ZenMod<Plugin>.Hotload.PrefabInit += Startup.InitPrefabs;
		}

		protected override void TitleScene(bool isFirstBoot)
		{
		}

		protected override void WorldStart()
		{
		}

		protected override void Shutdown()
		{
		}

		protected override void HotRestore()
		{
			GameObject[] array = Object.FindObjectsByType<GameObject>((FindObjectsSortMode)0);
			foreach (GameObject val in array)
			{
				switch (((Object)val).name)
				{
				case "ArmorStand(Clone)":
					Startup.AddContainer<ArmorStandContainer>(val);
					break;
				case "itemstand(Clone)":
				case "itemstandh(Clone)":
					Startup.AddContainer<ItemStandContainer>(val);
					break;
				}
			}
		}
	}
	public abstract class StandContainer : Container
	{
		public bool IsOpen
		{
			get
			{
				if (StandUI.IsOpen)
				{
					return (Object)(object)StandUI.Opened == (Object)(object)this;
				}
				return false;
			}
		}

		public abstract void ShowErrorMessage();

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

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

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

		public abstract void SwapEquip();

		protected abstract void UpdateVisualFromContainer();

		protected abstract bool FillContainer();

		protected abstract bool IsStandInventoryDiff();

		internal static void UpdateContainer(GameObject g)
		{
			if (g.HasContainerStand(out StandContainer c) && !c.IsOpen)
			{
				Log.Debug((object)$"Updating container: {((object)c).GetType()}", (ushort)0);
				c.TryFill();
			}
		}

		protected virtual void Awake()
		{
			((Container)this).Awake();
			if (ZNetView.m_forceDisableInit)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			Inventory inventory = ((Container)this).GetInventory();
			inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged));
			ZenMod<Plugin>.Hotload.Track((Object)(object)this);
		}

		private void OnInventoryChanged()
		{
			if (IsOpen)
			{
				UpdateVisualFromContainer();
				ShowHideStackAllButton();
			}
		}

		private void OnDestroy()
		{
			base.m_nview.Unregister("RequestOpen");
			base.m_nview.Unregister("OpenRespons");
			base.m_nview.Unregister("RPC_RequestStack");
			base.m_nview.Unregister("RPC_StackResponse");
			base.m_nview.Unregister("RequestTakeAll");
			base.m_nview.Unregister("TakeAllRespons");
			ZenMod<Plugin>.Hotload.Untrack((Object)(object)this);
		}

		public bool TryFill()
		{
			bool loading = base.m_loading;
			base.m_loading = true;
			bool result = IsStandInventoryDiff() && FillContainer();
			base.m_loading = loading;
			return result;
		}

		private bool CanFill()
		{
			if (((Container)this).IsOwner() || base.m_loading)
			{
				return true;
			}
			Log.Error((object)"Not Container owner && m_loading is false", (ushort)0);
			return false;
		}

		protected ItemData? GetItemData(string itemName, int index = -1)
		{
			//IL_001a: Expected O, but got Unknown
			try
			{
				return ZdoExt.GetItemData(base.m_nview.GetZDO(), itemName, index);
			}
			catch (MissingItemException val)
			{
				Log.Warning((object)((Exception)val).Message, (ushort)0);
				return null;
			}
		}

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

		public virtual void ShowHideStackAllButton()
		{
			InventoryGuiExt.ShowStackAllButton(InventoryGui.instance, IsAnyItemEquipable());
		}
	}
}