Decompiled source of ArmorGallery v1.0.1

ArmorGallery.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace ArmorGallery;

public enum RotationMode
{
	Sequential,
	RandomRow,
	Chaos
}
[BepInPlugin("com.drakosdj.armorgallery", "ArmorGallery", "1.0.1")]
public class ArmorGalleryPlugin : BaseUnityPlugin
{
	public static ArmorGalleryPlugin instance;

	public static ConfigEntry<bool> configEnabled;

	public static ConfigEntry<float> configRotationInterval;

	public static ConfigEntry<float> configLinkRadius;

	public static ConfigEntry<int> configMaxLinkedChests;

	public static ConfigEntry<float> configMaxLinkDistance;

	public static ConfigEntry<KeyCode> configPrevChestKey;

	public static ConfigEntry<KeyCode> configNextChestKey;

	public static ConfigEntry<RotationMode> configRotationMode;

	public static ConfigEntry<KeyCode> configModifierKey;

	public static ConfigEntry<KeyCode> configPoseModifierKey;

	public static ConfigEntry<bool> configRandomizePoseOnCycle;

	public static ConfigEntry<bool> configRandomizeStanceOnCycle;

	public static readonly HashSet<long> s_moddedPeers = new HashSet<long>();

	private void Awake()
	{
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Expected O, but got Unknown
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Expected O, but got Unknown
		instance = this;
		configEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the automatic cycling of armor stand sets.");
		configRotationInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RotationInterval", 60f, "Time in seconds between set rotations.");
		configLinkRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "LinkRadius", 20f, "Maximum distance in meters to find a chest to link.");
		configMaxLinkedChests = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxLinkedChests", 6, new ConfigDescription("Maximum number of chests that can be linked to a single Armor Stand.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 12), new object[0]));
		configMaxLinkDistance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MaxLinkDistance", 20f, new ConfigDescription("Maximum distance in meters between an Armor Stand and a linked chest.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 30f), new object[0]));
		configPrevChestKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "PrevChestKey", (KeyCode)113, "Hotkey to navigate to the previous linked chest in the UI.");
		configNextChestKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "NextChestKey", (KeyCode)101, "Hotkey to navigate to the next linked chest in the UI.");
		configRotationMode = ((BaseUnityPlugin)this).Config.Bind<RotationMode>("General", "RotationMode", RotationMode.Sequential, "Set cycling mode: Sequential (cycles row by row in order), RandomRow (picks a random set row each cycle), Chaos (mix-and-matches individual armor and weapon slots from random rows).");
		configRotationMode.SettingChanged += delegate
		{
			foreach (ArmorGalleryRotator s_allRotator in ArmorGalleryRotator.s_allRotators)
			{
				if ((Object)(object)s_allRotator != (Object)null && (Object)(object)s_allRotator.m_stand != (Object)null)
				{
					s_allRotator.UpdateStandVisualsFromActiveRow();
				}
			}
		};
		configRandomizePoseOnCycle = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RandomizePoseOnCycle", false, "When enabled, automatically chooses a random pose for the Armor Stand on each rotation cycle.");
		configRandomizeStanceOnCycle = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RandomizeStanceOnCycle", false, "When enabled, randomly alternates weapons between Equipped and Stowed on each rotation cycle.");
		configModifierKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ModifierKey", (KeyCode)304, "Modifier key to hold while pressing Use to toggle gallery linking mode on/off.");
		configPoseModifierKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "PoseModifierKey", (KeyCode)308, "Modifier key to hold while pressing Use to cycle armor stand pose.");
		Harmony val = new Harmony("com.drakosdj.armorgallery");
		val.PatchAll();
		Debug.Log((object)"[ArmorGallery] Plugin loaded successfully!");
	}

	public static void RegisterPeerRPCs()
	{
		if (ZRoutedRpc.instance != null)
		{
			ZRoutedRpc.instance.Register<bool>("AG_ModdedPeerAnnounce", (Action<long, bool>)RPC_ModdedPeerAnnounce);
			ZRoutedRpc.instance.Register<long>("AG_ModdedPeerQuery", (Action<long, long>)RPC_ModdedPeerQuery);
		}
	}

	private static void RPC_ModdedPeerAnnounce(long sender, bool isModded)
	{
		if (isModded && !s_moddedPeers.Contains(sender))
		{
			s_moddedPeers.Add(sender);
			if (ZRoutedRpc.instance != null && sender != ZRoutedRpc.Everybody)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, "AG_ModdedPeerAnnounce", new object[1] { true });
			}
		}
	}

	private static void RPC_ModdedPeerQuery(long sender, long target)
	{
		if (ZRoutedRpc.instance != null)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC(sender, "AG_ModdedPeerAnnounce", new object[1] { true });
		}
	}

	public static void AnnouncePresence()
	{
		if (ZRoutedRpc.instance != null)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "AG_ModdedPeerAnnounce", new object[1] { true });
		}
	}

	public static int GetActiveModdedPeerCount()
	{
		if ((Object)(object)ZNet.instance == (Object)null)
		{
			return 1;
		}
		List<ZNetPeer> peers = ZNet.instance.GetPeers();
		int num = 1;
		if (peers != null)
		{
			foreach (ZNetPeer item in peers)
			{
				if (item != null && item.IsReady() && s_moddedPeers.Contains(item.m_uid))
				{
					num++;
				}
			}
		}
		return num;
	}

	public static string GetUseKeyName()
	{
		try
		{
			if (ZInput.instance != null)
			{
				string boundKeyString = ZInput.instance.GetBoundKeyString("Use", false);
				if (!string.IsNullOrEmpty(boundKeyString))
				{
					return boundKeyString;
				}
			}
		}
		catch
		{
		}
		return "Use";
	}
}
[HarmonyPatch(typeof(ArmorStand), "Awake")]
public static class ArmorStand_Awake_Patch
{
	public static void Postfix(ArmorStand __instance)
	{
		if ((Object)(object)((Component)__instance).GetComponent<ArmorGalleryRotator>() == (Object)null)
		{
			((Component)__instance).gameObject.AddComponent<ArmorGalleryRotator>();
		}
	}
}
[HarmonyPatch(typeof(Switch), "GetHoverText")]
public static class Switch_GetHoverText_Patch
{
	public static void Postfix(Switch __instance, ref string __result)
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)__instance == (Object)null)
		{
			return;
		}
		ArmorStand componentInParent = ((Component)__instance).GetComponentInParent<ArmorStand>();
		if ((Object)(object)componentInParent == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return;
		}
		ArmorGalleryRotator component2 = ((Component)componentInParent).GetComponent<ArmorGalleryRotator>();
		if ((Object)(object)component2 == (Object)null)
		{
			return;
		}
		string useKeyName = ArmorGalleryPlugin.GetUseKeyName();
		string arg = ((object)ArmorGalleryPlugin.configModifierKey.Value).ToString();
		string text = ((object)ArmorGalleryPlugin.configPoseModifierKey.Value).ToString();
		int num = component2.GetCurrentPose() + 1;
		int maxPoses = component2.GetMaxPoses();
		if ((Object)(object)ArmorGalleryRotator.s_activeLinkingStand == (Object)(object)component2)
		{
			int count = component2.GetLinkedChests().Count;
			string arg2 = string.Format("<color=#FFD700>[Armor Gallery: In Linking Mode ({0} chest{1} linked)]</color>", count, (count == 1) ? "" : "s");
			string arg3 = $"\n[{arg} + {useKeyName}] Exit Linking Mode";
			__result = $"{__result}\n{arg2}{arg3}";
		}
		else if (component.GetZDO().GetBool("InLinkMode", false) && (Object)(object)ArmorGalleryRotator.s_activeLinkingStand != (Object)(object)component2)
		{
			string text2 = component.GetZDO().GetString("LinkUser", "another player");
			if (string.IsNullOrEmpty(text2))
			{
				text2 = "another player";
			}
			string arg4 = $"<color=#FFAA00>[Armor Gallery: Currently being edited by {text2}]</color>";
			string arg5 = $"\n[{text} + {useKeyName}] Change Pose ({num}/{maxPoses})";
			__result = $"{__result}\n{arg4}{arg5}";
		}
		else if (component.GetZDO().GetBool("RotationEnabled", false))
		{
			int count2 = component2.GetLinkedChests().Count;
			string arg2 = string.Format("<color=#FFD700>[Armor Gallery: Linked ({0} chest{1})]</color>", count2, (count2 == 1) ? "" : "s");
			string text3 = $"\n[{useKeyName}] Open Gallery Chest";
			string text4 = $"\n[{arg} + {useKeyName}] Edit Linked Chests";
			string arg5 = $"\n[{text} + {useKeyName}] Change Pose ({num}/{maxPoses})";
			__result = $"{__result}\n{arg2}{text3}{text4}{arg5}";
		}
		else
		{
			string arg2 = "<color=#AAAAAA>[Armor Gallery: Unlinked]</color>";
			string text4 = $"\n[{arg} + {useKeyName}] Enter Linking Mode";
			string arg5 = $"\n[{text} + {useKeyName}] Change Pose ({num}/{maxPoses})";
			__result = $"{__result}\n{arg2}{text4}{arg5}";
		}
	}
}
[HarmonyPatch(typeof(ArmorStand), "UseItem")]
public static class ArmorStand_UseItem_Patch
{
	public static bool Prefix(ArmorStand __instance, Switch caller, Humanoid user, ItemData item, ref bool __result)
	{
		//IL_000d: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		ArmorGalleryRotator component = ((Component)__instance).GetComponent<ArmorGalleryRotator>();
		if (Input.GetKey(ArmorGalleryPlugin.configModifierKey.Value))
		{
			if ((Object)(object)component != (Object)null)
			{
				component.ToggleLinkingMode();
			}
			__result = true;
			return false;
		}
		if (Input.GetKey(ArmorGalleryPlugin.configPoseModifierKey.Value))
		{
			if ((Object)(object)component != (Object)null)
			{
				component.CyclePose();
			}
			__result = true;
			return false;
		}
		if ((Object)(object)ArmorGalleryRotator.s_activeLinkingStand != (Object)null)
		{
			if ((Object)(object)ArmorGalleryRotator.s_activeLinkingStand == (Object)(object)component)
			{
				string useKeyName = ArmorGalleryPlugin.GetUseKeyName();
				string arg = ((object)ArmorGalleryPlugin.configModifierKey.Value).ToString();
				Player val = (Player)(object)((user is Player) ? user : null);
				if ((Object)(object)val != (Object)null)
				{
					((Character)val).Message((MessageType)2, string.Format("Armor Gallery: Aim at chests and press [{0}] to toggle link, or [{1} + {0}] to exit Linking Mode.", useKeyName, arg), 0, (Sprite)null);
				}
			}
			__result = true;
			return false;
		}
		ZNetView component2 = ((Component)__instance).GetComponent<ZNetView>();
		if ((Object)(object)component2 != (Object)null && component2.IsValid() && component2.GetZDO().GetBool("RotationEnabled", false) && (Object)(object)caller != (Object)(object)__instance.m_changePoseSwitch)
		{
			Container val2 = (((Object)(object)component != (Object)null) ? component.GetPrimaryChest() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				val2.Interact(user, false, false);
			}
			else
			{
				Player val = (Player)(object)((user is Player) ? user : null);
				if ((Object)(object)val != (Object)null)
				{
					string useKeyName = ArmorGalleryPlugin.GetUseKeyName();
					string arg = ((object)ArmorGalleryPlugin.configModifierKey.Value).ToString();
					string arg2 = ((object)ArmorGalleryPlugin.configPoseModifierKey.Value).ToString();
					((Character)val).Message((MessageType)2, string.Format("Armor Gallery: Manage items in chest, [{0} + {1}] for Pose, or [{2} + {1}] to edit links.", arg2, useKeyName, arg), 0, (Sprite)null);
				}
			}
			__result = true;
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(ArmorStand), "DropItem")]
public static class ArmorStand_DropItem_Patch
{
	public static bool Prefix(ArmorStand __instance, int index)
	{
		ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetBool("RotationEnabled", false))
		{
			return false;
		}
		return true;
	}
}
public static class ArmorGalleryMessaging
{
	public static void SendMessageToPlayer(long sender, Vector3 position, string msg)
	{
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		bool flag = false;
		if (sender != 0 && sender != ZRoutedRpc.Everybody)
		{
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				if ((Object)(object)allPlayer != (Object)null)
				{
					ZNetView component = ((Component)allPlayer).GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO() != null && component.GetZDO().GetOwner() == sender)
					{
						component.InvokeRPC(sender, "Message", new object[3] { 2, msg, 0 });
						flag = true;
						break;
					}
				}
			}
		}
		if (!flag)
		{
			Player.MessageAllInRange(position, 6f, (MessageType)2, msg, (Sprite)null);
		}
	}
}
[HarmonyPatch(typeof(ArmorStand), "RPC_DropItem")]
public static class ArmorStand_RPC_DropItem_Patch
{
	public static bool Prefix(ArmorStand __instance, long sender, int index)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetBool("RotationEnabled", false))
		{
			ArmorGalleryMessaging.SendMessageToPlayer(sender, ((Component)__instance).transform.position, "Armor Gallery: Manage armor sets in the linked chest.");
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(ArmorStand), "RPC_DropItemByName")]
public static class ArmorStand_RPC_DropItemByName_Patch
{
	public static bool Prefix(ArmorStand __instance, long sender, string name)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetBool("RotationEnabled", false))
		{
			ArmorGalleryMessaging.SendMessageToPlayer(sender, ((Component)__instance).transform.position, "Armor Gallery: Manage armor sets in the linked chest.");
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(ArmorStand), "RPC_DestroyAttachment")]
public static class ArmorStand_RPC_DestroyAttachment_Patch
{
	public static bool Prefix(ArmorStand __instance, long sender, int index)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetBool("RotationEnabled", false))
		{
			ArmorGalleryMessaging.SendMessageToPlayer(sender, ((Component)__instance).transform.position, "Armor Gallery: Manage armor sets in the linked chest.");
			return false;
		}
		return true;
	}
}
public class ArmorGalleryRotator : MonoBehaviour
{
	public struct SetRef
	{
		public Container Chest;

		public int ChestIndex;

		public int ChestRow;

		public int GlobalSetNumber;
	}

	public static ArmorGalleryRotator s_activeLinkingStand = null;

	public static readonly List<ArmorGalleryRotator> s_allRotators = new List<ArmorGalleryRotator>();

	internal ArmorStand m_stand;

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

	private readonly List<GameObject> m_connectionInstances = new List<GameObject>();

	private float m_timer;

	internal int m_activeSetIndex = 0;

	private bool m_isSyncing = false;

	private bool m_wasChestInUse = false;

	private bool m_wasAlreadyEnabledBeforeLinking = false;

	private static int[] s_itemKeyHashes;

	private static int[] s_variantKeyHashes;

	private float m_hudMsgTimer = 0f;

	private static readonly MethodInfo s_setVisualItemMethod = typeof(ArmorStand).GetMethod("SetVisualItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly MethodInfo s_updateVisualsMethod = typeof(VisEquipment).GetMethod("UpdateVisuals", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo[] s_currentHashFields = new FieldInfo[13]
	{
		typeof(VisEquipment).GetField("m_currentHelmetItemHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
		typeof(VisEquipment).GetField("m_currentChestItemHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
		typeof(VisEquipment).GetField("m_currentLegItemHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
		typeof(VisEquipment).GetField("m_currentShoulderItemHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
		typeof(VisEquipment).GetField("m_currentLeftItemHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
		typeof(VisEquipment).GetField("m_currentRightItemHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
		typeof(VisEquipment).GetField("m_currentLeftBackItemHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
		typeof(VisEquipment).GetField("m_currentRightBackItemHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
		typeof(VisEquipment).GetField("m_currentUtilityItemHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
		typeof(VisEquipment).GetField("m_currentTrinketItemHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
		typeof(VisEquipment).GetField("m_currentShoulderItemVariant", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
		typeof(VisEquipment).GetField("m_currentLeftItemVariant", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic),
		typeof(VisEquipment).GetField("m_currentLeftBackItemVariant", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
	};

	private static GameObject s_connectionPrefab;

	private static readonly VisSlot[] UI_COLUMN_SLOTS = (VisSlot[])(object)new VisSlot[6]
	{
		(VisSlot)6,
		(VisSlot)4,
		(VisSlot)5,
		default(VisSlot),
		(VisSlot)1,
		(VisSlot)7
	};

	public Container GetPrimaryChest()
	{
		List<Container> linkedChests = GetLinkedChests();
		return (linkedChests.Count > 0) ? linkedChests[0] : null;
	}

	public Container GetLinkedChest()
	{
		return GetPrimaryChest();
	}

	public List<Container> GetLinkedChests()
	{
		ValidateAndPruneLinkedChests();
		return m_linkedChests;
	}

	public bool IsChestLinked(Container chest)
	{
		if ((Object)(object)chest == (Object)null)
		{
			return false;
		}
		return GetLinkedChests().Contains(chest);
	}

	public int GetCurrentPose()
	{
		if ((Object)(object)m_stand == (Object)null)
		{
			return 0;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return 0;
		}
		return component.GetZDO().GetInt(ZDOVars.s_pose, 0);
	}

	public int GetMaxPoses()
	{
		return ((Object)(object)m_stand != (Object)null && m_stand.m_poseCount > 0) ? m_stand.m_poseCount : 8;
	}

	public void CyclePose()
	{
		if ((Object)(object)m_stand == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if (!((Object)(object)component == (Object)null) && component.IsValid())
		{
			int maxPoses = GetMaxPoses();
			int num = component.GetZDO().GetInt(ZDOVars.s_pose, 0);
			int num2 = (num + 1) % maxPoses;
			component.InvokeRPC(ZRoutedRpc.Everybody, "RPC_SetPose", new object[1] { num2 });
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, $"Armor Stand: Pose {num2 + 1}/{maxPoses}", 0, (Sprite)null);
			}
		}
	}

	public void SetPose(int poseIndex)
	{
		if (!((Object)(object)m_stand == (Object)null))
		{
			ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid())
			{
				int maxPoses = GetMaxPoses();
				int num = Mathf.Clamp(poseIndex, 0, maxPoses - 1);
				component.InvokeRPC(ZRoutedRpc.Everybody, "RPC_SetPose", new object[1] { num });
			}
		}
	}

	public void SetRandomPose()
	{
		int maxPoses = GetMaxPoses();
		if (maxPoses <= 1)
		{
			return;
		}
		List<int> list = new List<int>();
		for (int i = 0; i < maxPoses; i++)
		{
			if (i != 14)
			{
				list.Add(i);
			}
		}
		if (list.Count != 0)
		{
			int pose = list[Random.Range(0, list.Count)];
			SetPose(pose);
		}
	}

	private static int[] GetItemKeyHashes()
	{
		if (s_itemKeyHashes == null)
		{
			FieldInfo field = typeof(ArmorStand).GetField("s_itemKeyHashes", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				s_itemKeyHashes = (int[])field.GetValue(null);
			}
		}
		return s_itemKeyHashes;
	}

	private static int[] GetVariantKeyHashes()
	{
		if (s_variantKeyHashes == null)
		{
			FieldInfo field = typeof(ArmorStand).GetField("s_variantKeyHashes", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				s_variantKeyHashes = (int[])field.GetValue(null);
			}
		}
		return s_variantKeyHashes;
	}

	public static void HandleLogout()
	{
		try
		{
			if (ArmorGalleryPlugin.GetActiveModdedPeerCount() > 1)
			{
				Debug.Log((object)"[ArmorGallery] Other modded players remain connected; preserving active stand displays.");
				return;
			}
			Debug.Log((object)"[ArmorGallery] Last modded player logging out; securing stands and committing all items into chests.");
			foreach (ArmorGalleryRotator s_allRotator in s_allRotators)
			{
				if ((Object)(object)s_allRotator != (Object)null && (Object)(object)s_allRotator.m_stand != (Object)null)
				{
					ZNetView component = ((Component)s_allRotator.m_stand).GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetBool("RotationEnabled", false))
					{
						s_allRotator.ClearStandItemsAndVisuals();
					}
				}
			}
		}
		catch (Exception arg)
		{
			Debug.LogError((object)$"[ArmorGallery] Error during HandleLogout: {arg}");
		}
	}

	private void Awake()
	{
		m_stand = ((Component)this).GetComponent<ArmorStand>();
		m_timer = Random.Range(0f, ArmorGalleryPlugin.configRotationInterval.Value * 0.25f);
		if (!s_allRotators.Contains(this))
		{
			s_allRotators.Add(this);
		}
	}

	private void Start()
	{
		if ((Object)(object)m_stand == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetBool("RotationEnabled", false))
		{
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			LoadLinkedChestsFromZDO();
			ValidateAndPruneLinkedChests();
			if (m_linkedChests.Count > 0)
			{
				UpdateStandVisualsFromActiveRow();
			}
		}
	}

	private void Update()
	{
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		if (!ArmorGalleryPlugin.configEnabled.Value || (Object)(object)m_stand == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return;
		}
		bool flag = (Object)(object)s_activeLinkingStand == (Object)(object)this;
		bool flag2 = component.GetZDO().GetBool("InLinkMode", false);
		if (flag || flag2)
		{
			UpdateConnectionEffectsContinuous();
			if (flag && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				m_hudMsgTimer += Time.deltaTime;
				if (m_hudMsgTimer >= 0.5f)
				{
					m_hudMsgTimer = 0f;
					string useKeyName = ArmorGalleryPlugin.GetUseKeyName();
					string arg = ((object)ArmorGalleryPlugin.configModifierKey.Value).ToString();
					int count = m_linkedChests.Count;
					string arg2 = string.Format("{0} chest{1} linked", count, (count == 1) ? "" : "s");
					string text = string.Format("<color=#FFD700><b>[ARMOR GALLERY: LINKING MODE]</b></color>\n<color=#FFFFFF>{0}\n• Aim at chest + [{1}] to toggle link\n• Aim at stand + [{2} + {1}] to exit</color>", arg2, useKeyName, arg);
					((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null);
				}
			}
		}
		else if (m_connectionInstances.Count > 0)
		{
			StopConnectionEffects();
		}
		if (!component.GetZDO().GetBool("RotationEnabled", false))
		{
			return;
		}
		if ((Object)(object)s_activeLinkingStand != (Object)(object)this)
		{
			Player closestPlayer = Player.GetClosestPlayer(((Component)m_stand).transform.position, 64f);
			if ((Object)(object)closestPlayer != (Object)null && (Object)(object)closestPlayer != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
		}
		if (!component.IsOwner())
		{
			component.ClaimOwnership();
		}
		ValidateAndPruneLinkedChests();
		if (m_linkedChests.Count == 0)
		{
			ClearStandItemsAndVisuals();
			ClearLink();
			return;
		}
		bool flag3 = false;
		for (int i = 0; i < m_linkedChests.Count; i++)
		{
			if ((Object)(object)m_linkedChests[i] != (Object)null && m_linkedChests[i].IsInUse())
			{
				flag3 = true;
				break;
			}
		}
		if (m_wasChestInUse && !flag3)
		{
			UpdateStandVisualsFromActiveRow();
		}
		m_wasChestInUse = flag3;
		m_timer += Time.deltaTime;
		if (m_timer >= ArmorGalleryPlugin.configRotationInterval.Value)
		{
			m_timer = 0f;
			TryRotateSet();
		}
	}

	public void SaveLinkedChestsToZDO()
	{
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)m_stand == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return;
		}
		if (!component.IsOwner())
		{
			component.ClaimOwnership();
		}
		component.GetZDO().Set("LinkedChestCount", m_linkedChests.Count);
		for (int i = 0; i < m_linkedChests.Count; i++)
		{
			ZNetView val = (((Object)(object)m_linkedChests[i] != (Object)null) ? ((Component)m_linkedChests[i]).GetComponent<ZNetView>() : null);
			if ((Object)(object)val != (Object)null && val.IsValid())
			{
				component.GetZDO().Set("LinkedChest_" + i, val.GetZDO().m_uid);
			}
		}
		if (m_linkedChests.Count > 0 && (Object)(object)m_linkedChests[0] != (Object)null)
		{
			ZNetView component2 = ((Component)m_linkedChests[0]).GetComponent<ZNetView>();
			if ((Object)(object)component2 != (Object)null && component2.IsValid())
			{
				component.GetZDO().Set("LinkedChestID", component2.GetZDO().m_uid);
			}
		}
		else
		{
			component.GetZDO().Set("LinkedChestID", ZDOID.None);
		}
		component.GetZDO().Set("RotationEnabled", m_linkedChests.Count > 0);
	}

	public void LoadLinkedChestsFromZDO()
	{
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)m_stand == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return;
		}
		m_linkedChests.Clear();
		int num = component.GetZDO().GetInt("LinkedChestCount", -1);
		GameObject val;
		if (num >= 0)
		{
			for (int i = 0; i < num; i++)
			{
				ZDOID zDOID = component.GetZDO().GetZDOID("LinkedChest_" + i);
				if (((ZDOID)(ref zDOID)).IsNone())
				{
					continue;
				}
				val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.FindInstance(zDOID) : null);
				if (!((Object)(object)val != (Object)null))
				{
					continue;
				}
				Container component2 = val.GetComponent<Container>();
				if ((Object)(object)component2 != (Object)null && !m_linkedChests.Contains(component2))
				{
					float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)component2).transform.position);
					if (num2 <= ArmorGalleryPlugin.configMaxLinkDistance.Value)
					{
						m_linkedChests.Add(component2);
					}
				}
			}
			return;
		}
		ZDOID zDOID2 = component.GetZDO().GetZDOID("LinkedChestID");
		if (((ZDOID)(ref zDOID2)).IsNone())
		{
			return;
		}
		val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.FindInstance(zDOID2) : null);
		if ((Object)(object)val != (Object)null)
		{
			Container component2 = val.GetComponent<Container>();
			if ((Object)(object)component2 != (Object)null)
			{
				m_linkedChests.Add(component2);
			}
		}
	}

	private void ValidateAndPruneLinkedChests()
	{
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)s_activeLinkingStand != (Object)(object)this)
		{
			LoadLinkedChestsFromZDO();
		}
		bool flag = false;
		for (int num = m_linkedChests.Count - 1; num >= 0; num--)
		{
			Container val = m_linkedChests[num];
			if ((Object)(object)val == (Object)null || !((Component)val).gameObject.activeInHierarchy)
			{
				m_linkedChests.RemoveAt(num);
				flag = true;
			}
			else
			{
				float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)val).transform.position);
				if (num2 > ArmorGalleryPlugin.configMaxLinkDistance.Value)
				{
					Debug.Log((object)$"[ArmorGallery] Chest at {((Component)val).transform.position} exceeded max distance ({num2:F1}m > {ArmorGalleryPlugin.configMaxLinkDistance.Value}m), unlinking.");
					m_linkedChests.RemoveAt(num);
					flag = true;
				}
			}
		}
		if (flag && (Object)(object)s_activeLinkingStand == (Object)(object)this)
		{
			SaveLinkedChestsToZDO();
		}
	}

	public void ToggleLinkingMode()
	{
		string useKeyName = ArmorGalleryPlugin.GetUseKeyName();
		ZNetView component;
		if ((Object)(object)s_activeLinkingStand == (Object)(object)this)
		{
			s_activeLinkingStand = null;
			ValidateAndPruneLinkedChests();
			component = ((Component)m_stand).GetComponent<ZNetView>();
			if (!((Object)(object)component != (Object)null) || !component.IsValid())
			{
				return;
			}
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			component.GetZDO().Set("InLinkMode", false);
			component.GetZDO().Set("LinkUser", "");
			component.GetZDO().Set("LinkUserID", 0L);
			if (m_linkedChests.Count > 0)
			{
				if (!m_wasAlreadyEnabledBeforeLinking)
				{
					SaveStandItemsToChest();
				}
				component.GetZDO().Set("RotationEnabled", true);
				SaveLinkedChestsToZDO();
				m_timer = 0f;
				UpdateStandVisualsFromActiveRow();
				StopConnectionEffects();
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, string.Format("Armor Gallery: Linking Mode Finished ({0} chest{1} linked)", m_linkedChests.Count, (m_linkedChests.Count == 1) ? "" : "s"), 0, (Sprite)null);
				}
			}
			else
			{
				ClearStandItemsAndVisuals();
				ClearLink();
				StopConnectionEffects();
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "Armor Gallery: Linking Mode Finished (Unlinked)", 0, (Sprite)null);
				}
			}
			return;
		}
		component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && component.IsValid())
		{
			bool flag = component.GetZDO().GetBool("InLinkMode", false);
			long num = component.GetZDO().GetLong("LinkUserID", 0L);
			long num2 = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0);
			if (flag && num != 0 && num != num2)
			{
				string text = component.GetZDO().GetString("LinkUser", "another player");
				if (string.IsNullOrEmpty(text))
				{
					text = "another player";
				}
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, $"Armor Gallery: Stand is currently being edited by {text}!", 0, (Sprite)null);
				}
				return;
			}
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			m_wasAlreadyEnabledBeforeLinking = component.GetZDO().GetBool("RotationEnabled", false);
			component.GetZDO().Set("InLinkMode", true);
			component.GetZDO().Set("LinkUser", ((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerName() : "A Viking");
			component.GetZDO().Set("LinkUserID", num2);
		}
		s_activeLinkingStand = this;
		LoadLinkedChestsFromZDO();
		UpdateConnectionEffectsContinuous();
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, string.Format("Armor Gallery: Linking Mode Started ({0} chest{1} linked).\nLook at a chest and press [{2}] to toggle link.", m_linkedChests.Count, (m_linkedChests.Count == 1) ? "" : "s", useKeyName), 0, (Sprite)null);
		}
	}

	public static ArmorGalleryRotator GetRotatorLinkingChest(Container chest)
	{
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)chest == (Object)null)
		{
			return null;
		}
		foreach (ArmorGalleryRotator s_allRotator in s_allRotators)
		{
			if ((Object)(object)s_allRotator != (Object)null && (Object)(object)s_allRotator.m_stand != (Object)null && s_allRotator.IsChestLinked(chest))
			{
				return s_allRotator;
			}
		}
		float num = ArmorGalleryPlugin.configMaxLinkDistance.Value + 2f;
		Collider[] array = Physics.OverlapSphere(((Component)chest).transform.position, num);
		Collider[] array2 = array;
		foreach (Collider val in array2)
		{
			ArmorStand componentInParent = ((Component)val).GetComponentInParent<ArmorStand>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				ArmorGalleryRotator current = ((Component)componentInParent).GetComponent<ArmorGalleryRotator>();
				if ((Object)(object)current != (Object)null && current.IsChestLinked(chest))
				{
					return current;
				}
			}
		}
		return null;
	}

	public bool ToggleChestLink(Container chest)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)chest == (Object)null)
		{
			return false;
		}
		float num = Vector3.Distance(((Component)this).transform.position, ((Component)chest).transform.position);
		if (num > ArmorGalleryPlugin.configMaxLinkDistance.Value)
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, $"Armor Gallery: Chest is too far away ({num:F1}m > {ArmorGalleryPlugin.configMaxLinkDistance.Value}m max)!", 0, (Sprite)null);
			}
			return false;
		}
		if (chest.GetInventory() != null && chest.GetInventory().GetWidth() < 5)
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Armor Gallery: Chest must have at least 5 columns!", 0, (Sprite)null);
			}
			return false;
		}
		if (((Object)chest).name.ToLower().Contains("private") || ((Object)chest).name.ToLower().Contains("personal"))
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Armor Gallery: Private/personal chests cannot be linked!", 0, (Sprite)null);
			}
			return false;
		}
		if (IsChestLinked(chest))
		{
			m_linkedChests.Remove(chest);
			SaveLinkedChestsToZDO();
			if (m_linkedChests.Count == 0)
			{
				ClearStandItemsAndVisuals();
			}
			else
			{
				UpdateStandVisualsFromActiveRow();
			}
			ShowConnectionEffects(6f);
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, string.Format("Armor Gallery: Chest Unlinked ({0} chest{1} remaining)", m_linkedChests.Count, (m_linkedChests.Count == 1) ? "" : "s"), 0, (Sprite)null);
			}
			return true;
		}
		ArmorGalleryRotator rotatorLinkingChest = GetRotatorLinkingChest(chest);
		if ((Object)(object)rotatorLinkingChest != (Object)null && (Object)(object)rotatorLinkingChest != (Object)(object)this)
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Armor Gallery: Chest is already linked to another Armor Stand!", 0, (Sprite)null);
			}
			return false;
		}
		if (m_linkedChests.Count >= ArmorGalleryPlugin.configMaxLinkedChests.Value)
		{
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, $"Armor Gallery: Maximum linked chests reached ({m_linkedChests.Count}/{ArmorGalleryPlugin.configMaxLinkedChests.Value})!", 0, (Sprite)null);
			}
			return false;
		}
		m_linkedChests.Add(chest);
		SaveLinkedChestsToZDO();
		ShowConnectionEffects(6f);
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, $"Armor Gallery: Chest Linked ({m_linkedChests.Count}/{ArmorGalleryPlugin.configMaxLinkedChests.Value} chests linked)", 0, (Sprite)null);
		}
		return true;
	}

	public void OnChestDestroyed(Container chest)
	{
		if ((Object)(object)chest != (Object)null && m_linkedChests.Contains(chest))
		{
			m_linkedChests.Remove(chest);
			SaveLinkedChestsToZDO();
			if (m_linkedChests.Count == 0)
			{
				ClearStandItemsAndVisuals();
				ClearLink();
			}
			else
			{
				UpdateStandVisualsFromActiveRow();
			}
		}
	}

	public List<SetRef> GetAllPopulatedSets()
	{
		List<SetRef> list = new List<SetRef>();
		List<Container> linkedChests = GetLinkedChests();
		int num = 1;
		for (int i = 0; i < linkedChests.Count; i++)
		{
			Container val = linkedChests[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			Inventory inventory = val.GetInventory();
			if (inventory == null)
			{
				continue;
			}
			int height = inventory.GetHeight();
			int width = inventory.GetWidth();
			int num2 = Math.Min(width, 6);
			for (int j = 0; j < height; j++)
			{
				bool flag = false;
				for (int k = 0; k < num2; k++)
				{
					if (inventory.GetItemAt(k, j) != null)
					{
						flag = true;
						break;
					}
				}
				if (flag)
				{
					list.Add(new SetRef
					{
						Chest = val,
						ChestIndex = i,
						ChestRow = j,
						GlobalSetNumber = num
					});
				}
				num++;
			}
		}
		return list;
	}

	public List<int> GetPopulatedRows(Inventory chestInventory)
	{
		List<int> list = new List<int>();
		if (chestInventory == null)
		{
			return list;
		}
		int height = chestInventory.GetHeight();
		int width = chestInventory.GetWidth();
		int num = Math.Min(width, 6);
		for (int i = 0; i < height; i++)
		{
			bool flag = false;
			for (int j = 0; j < num; j++)
			{
				if (chestInventory.GetItemAt(j, i) != null)
				{
					flag = true;
					break;
				}
			}
			if (flag)
			{
				list.Add(i);
			}
		}
		return list;
	}

	private void TryRotateSet()
	{
		List<Container> linkedChests = GetLinkedChests();
		if (linkedChests.Count == 0)
		{
			return;
		}
		for (int i = 0; i < linkedChests.Count; i++)
		{
			if ((Object)(object)linkedChests[i] != (Object)null && linkedChests[i].IsInUse())
			{
				return;
			}
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return;
		}
		if (!component.IsOwner())
		{
			component.ClaimOwnership();
		}
		List<SetRef> allPopulatedSets = GetAllPopulatedSets();
		if (allPopulatedSets.Count != 0)
		{
			if (ArmorGalleryPlugin.configRandomizePoseOnCycle.Value)
			{
				SetRandomPose();
			}
			if (ArmorGalleryPlugin.configRandomizeStanceOnCycle.Value)
			{
				SetRandomWeaponsEquipped();
			}
			switch (ArmorGalleryPlugin.configRotationMode.Value)
			{
			case RotationMode.Chaos:
				UpdateStandVisualsChaos();
				break;
			case RotationMode.RandomRow:
			{
				m_activeSetIndex = Random.Range(0, allPopulatedSets.Count);
				SetRef setRef = allPopulatedSets[m_activeSetIndex];
				UpdateStandVisuals(setRef.Chest, setRef.ChestRow, setRef.GlobalSetNumber);
				break;
			}
			default:
			{
				m_activeSetIndex = (m_activeSetIndex + 1) % allPopulatedSets.Count;
				SetRef setRef = allPopulatedSets[m_activeSetIndex];
				UpdateStandVisuals(setRef.Chest, setRef.ChestRow, setRef.GlobalSetNumber);
				break;
			}
			}
		}
	}

	public bool FindFirstEmptyChestRow(out Container targetChest, out int targetRow)
	{
		targetChest = null;
		targetRow = -1;
		List<Container> linkedChests = GetLinkedChests();
		for (int i = 0; i < linkedChests.Count; i++)
		{
			Container val = linkedChests[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			Inventory inventory = val.GetInventory();
			if (inventory == null)
			{
				continue;
			}
			int height = inventory.GetHeight();
			int width = inventory.GetWidth();
			for (int j = 0; j < height; j++)
			{
				bool flag = true;
				for (int k = 0; k < width; k++)
				{
					if (inventory.GetItemAt(k, j) != null)
					{
						flag = false;
						break;
					}
				}
				if (flag)
				{
					targetChest = val;
					targetRow = j;
					return true;
				}
			}
		}
		return false;
	}

	public void ClearStandItemsAndVisuals()
	{
		if ((Object)(object)m_stand == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return;
		}
		if (!component.IsOwner())
		{
			component.ClaimOwnership();
		}
		int[] itemKeyHashes = GetItemKeyHashes();
		int[] variantKeyHashes = GetVariantKeyHashes();
		for (int i = 0; i < m_stand.m_slots.Count; i++)
		{
			if (itemKeyHashes != null && i < itemKeyHashes.Length)
			{
				component.GetZDO().Set(itemKeyHashes[i], "");
			}
			if (variantKeyHashes != null && i < variantKeyHashes.Length)
			{
				component.GetZDO().Set(variantKeyHashes[i], 0, false);
			}
			component.GetZDO().Set(ZDOVars.s_item + i, "");
			if (i < m_stand.m_slots.Count && m_stand.m_slots[i] != null)
			{
				m_stand.m_slots[i].m_visualName = null;
				m_stand.m_slots[i].m_visualVariant = -1;
			}
			if (s_setVisualItemMethod != null)
			{
				s_setVisualItemMethod.Invoke(m_stand, new object[3] { i, "", 0 });
			}
			component.InvokeRPC(ZRoutedRpc.Everybody, "RPC_SetVisualItem", new object[3] { i, "", 0 });
		}
		component.GetZDO().Set(ZDOVars.s_helmetItem, 0, false);
		component.GetZDO().Set(ZDOVars.s_chestItem, 0, false);
		component.GetZDO().Set(ZDOVars.s_legItem, 0, false);
		component.GetZDO().Set(ZDOVars.s_shoulderItem, 0, false);
		component.GetZDO().Set(ZDOVars.s_shoulderItemVariant, 0, false);
		component.GetZDO().Set(ZDOVars.s_rightItem, 0, false);
		component.GetZDO().Set(ZDOVars.s_rightBackItem, 0, false);
		component.GetZDO().Set(ZDOVars.s_leftItem, 0, false);
		component.GetZDO().Set(ZDOVars.s_leftBackItem, 0, false);
		component.GetZDO().Set(ZDOVars.s_utilityItem, 0, false);
		if (!((Object)(object)m_stand.m_visEquipment != (Object)null))
		{
			return;
		}
		FieldInfo[] array = s_currentHashFields;
		foreach (FieldInfo fieldInfo in array)
		{
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(m_stand.m_visEquipment, -1);
			}
		}
		if (s_updateVisualsMethod != null)
		{
			s_updateVisualsMethod.Invoke(m_stand.m_visEquipment, null);
		}
	}

	public void ClearLink()
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		StopConnectionEffects();
		m_linkedChests.Clear();
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && component.IsValid())
		{
			component.GetZDO().Set("RotationEnabled", false);
			component.GetZDO().Set("LinkedChestID", ZDOID.None);
			component.GetZDO().Set("LinkedChestCount", 0);
			component.GetZDO().Set("InLinkMode", false);
			component.GetZDO().Set("LinkUser", "");
			component.GetZDO().Set("LinkUserID", 0L);
		}
		if ((Object)(object)m_stand != (Object)null)
		{
			((MonoBehaviour)m_stand).InvokeRepeating("UpdateVisual", 1f, 4f);
		}
	}

	public static GameObject GetConnectionPrefab()
	{
		if ((Object)(object)s_connectionPrefab != (Object)null)
		{
			return s_connectionPrefab;
		}
		if ((Object)(object)ZNetScene.instance != (Object)null)
		{
			string[] array = new string[7] { "piece_workbench_ext1", "piece_workbench_ext2", "piece_workbench_ext3", "piece_workbench_ext4", "piece_forge_ext1", "piece_forge_ext2", "piece_forge_ext3" };
			string[] array2 = array;
			foreach (string text in array2)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(text);
				if ((Object)(object)prefab != (Object)null)
				{
					StationExtension component = prefab.GetComponent<StationExtension>();
					if ((Object)(object)component != (Object)null && (Object)(object)component.m_connectionPrefab != (Object)null)
					{
						s_connectionPrefab = component.m_connectionPrefab;
						return s_connectionPrefab;
					}
				}
			}
		}
		return null;
	}

	public void UpdateConnectionEffectsContinuous()
	{
		//IL_0067: 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_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: 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_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)m_stand == (Object)null)
		{
			return;
		}
		List<Container> linkedChests = GetLinkedChests();
		if (linkedChests.Count == 0)
		{
			StopConnectionEffects();
			return;
		}
		GameObject connectionPrefab = GetConnectionPrefab();
		if ((Object)(object)connectionPrefab == (Object)null)
		{
			return;
		}
		Vector3 val = ((Component)m_stand).transform.position + Vector3.up * 0.9f;
		while (m_connectionInstances.Count < linkedChests.Count)
		{
			GameObject item = Object.Instantiate<GameObject>(connectionPrefab, val, Quaternion.identity);
			m_connectionInstances.Add(item);
		}
		while (m_connectionInstances.Count > linkedChests.Count)
		{
			int index = m_connectionInstances.Count - 1;
			if ((Object)(object)m_connectionInstances[index] != (Object)null)
			{
				Object.Destroy((Object)(object)m_connectionInstances[index]);
			}
			m_connectionInstances.RemoveAt(index);
		}
		for (int i = 0; i < linkedChests.Count; i++)
		{
			Container val2 = linkedChests[i];
			GameObject item = m_connectionInstances[i];
			if ((Object)(object)val2 != (Object)null && (Object)(object)item != (Object)null)
			{
				Vector3 val3 = ((Component)val2).transform.position + Vector3.up * 0.4f;
				Vector3 val4 = val - val3;
				item.transform.position = val3;
				item.transform.rotation = Quaternion.LookRotation(((Vector3)(ref val4)).normalized);
				item.transform.localScale = new Vector3(1f, 1f, ((Vector3)(ref val4)).magnitude);
			}
		}
	}

	public void ShowConnectionEffects(float duration = 4f)
	{
		UpdateConnectionEffectsContinuous();
		((MonoBehaviour)this).CancelInvoke("StopConnectionEffects");
		((MonoBehaviour)this).Invoke("StopConnectionEffects", duration);
	}

	public void StopConnectionEffects()
	{
		for (int i = 0; i < m_connectionInstances.Count; i++)
		{
			if ((Object)(object)m_connectionInstances[i] != (Object)null)
			{
				Object.Destroy((Object)(object)m_connectionInstances[i]);
			}
		}
		m_connectionInstances.Clear();
	}

	private void OnDisable()
	{
		StopConnectionEffects();
	}

	private void OnDestroy()
	{
		StopConnectionEffects();
		s_allRotators.Remove(this);
		if (!((Object)(object)s_activeLinkingStand == (Object)(object)this))
		{
			return;
		}
		s_activeLinkingStand = null;
		if ((Object)(object)m_stand != (Object)null)
		{
			ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				component.GetZDO().Set("InLinkMode", false);
				component.GetZDO().Set("LinkUser", "");
				component.GetZDO().Set("LinkUserID", 0L);
			}
		}
	}

	private static string GetItemPrefabName(ItemData item)
	{
		if (item == null)
		{
			return "";
		}
		if ((Object)(object)item.m_dropPrefab != (Object)null)
		{
			return ((Object)item.m_dropPrefab).name;
		}
		if ((Object)(object)ObjectDB.instance != (Object)null)
		{
			foreach (GameObject item2 in ObjectDB.instance.m_items)
			{
				if ((Object)(object)item2 != (Object)null)
				{
					ItemDrop component = item2.GetComponent<ItemDrop>();
					if ((Object)(object)component != (Object)null && component.m_itemData != null && component.m_itemData.m_shared != null && component.m_itemData.m_shared.m_name == item.m_shared.m_name)
					{
						return ((Object)item2).name;
					}
				}
			}
		}
		return "";
	}

	private static int GetStandSlotIndexForVisSlot(ArmorStand stand, VisSlot targetSlot)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: 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_005f: 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_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Invalid comparison between Unknown and I4
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Invalid comparison between Unknown and I4
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Invalid comparison between Unknown and I4
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Invalid comparison between Unknown and I4
		if ((Object)(object)stand == (Object)null || stand.m_slots == null)
		{
			return -1;
		}
		for (int i = 0; i < stand.m_slots.Count; i++)
		{
			if (stand.m_slots[i] != null)
			{
				VisSlot slot = stand.m_slots[i].m_slot;
				if (slot == targetSlot)
				{
					return i;
				}
				if ((int)targetSlot == 0 && ((int)slot == 0 || (int)slot == 2))
				{
					return i;
				}
				if ((int)targetSlot == 1 && ((int)slot == 1 || (int)slot == 3))
				{
					return i;
				}
			}
		}
		return -1;
	}

	public void UpdateStandVisualsFromActiveRow()
	{
		List<SetRef> allPopulatedSets = GetAllPopulatedSets();
		if (allPopulatedSets.Count == 0)
		{
			Container primaryChest = GetPrimaryChest();
			if ((Object)(object)primaryChest != (Object)null)
			{
				UpdateStandVisuals(primaryChest, 0, 1);
			}
			return;
		}
		if (m_activeSetIndex >= allPopulatedSets.Count)
		{
			m_activeSetIndex = 0;
		}
		if (ArmorGalleryPlugin.configRotationMode.Value == RotationMode.Chaos)
		{
			UpdateStandVisualsChaos();
			return;
		}
		SetRef setRef = allPopulatedSets[m_activeSetIndex];
		UpdateStandVisuals(setRef.Chest, setRef.ChestRow, setRef.GlobalSetNumber);
	}

	public void UpdateStandVisuals(Container chest, int row, int globalSetNumber)
	{
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Invalid comparison between Unknown and I4
		//IL_0234: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Invalid comparison between Unknown and I4
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Invalid comparison between Unknown and I4
		//IL_027d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0283: Invalid comparison between Unknown and I4
		//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c7: Invalid comparison between Unknown and I4
		//IL_0310: Unknown result type (might be due to invalid IL or missing references)
		//IL_0315: Unknown result type (might be due to invalid IL or missing references)
		//IL_031b: Unknown result type (might be due to invalid IL or missing references)
		//IL_031e: Invalid comparison between Unknown and I4
		//IL_041e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0426: Unknown result type (might be due to invalid IL or missing references)
		//IL_033a: Unknown result type (might be due to invalid IL or missing references)
		//IL_033d: Invalid comparison between Unknown and I4
		//IL_0356: Unknown result type (might be due to invalid IL or missing references)
		//IL_035a: Invalid comparison between Unknown and I4
		//IL_0373: Unknown result type (might be due to invalid IL or missing references)
		//IL_0376: Invalid comparison between Unknown and I4
		//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b4: Invalid comparison between Unknown and I4
		if (m_isSyncing || (Object)(object)chest == (Object)null || (Object)(object)m_stand == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return;
		}
		if (!component.IsOwner())
		{
			component.ClaimOwnership();
		}
		Inventory inventory = chest.GetInventory();
		if (inventory == null)
		{
			return;
		}
		int[] itemKeyHashes = GetItemKeyHashes();
		int[] variantKeyHashes = GetVariantKeyHashes();
		if (itemKeyHashes == null)
		{
			return;
		}
		m_isSyncing = true;
		component.GetZDO().Set("ActiveSetRow", row);
		component.GetZDO().Set("ActiveGlobalSet", globalSetNumber);
		for (int i = 0; i < m_stand.m_slots.Count; i++)
		{
			if (m_stand.m_slots[i] != null)
			{
				m_stand.m_slots[i].m_visualName = null;
				m_stand.m_slots[i].m_visualVariant = -1;
			}
		}
		if ((Object)(object)m_stand.m_visEquipment != (Object)null)
		{
			for (int j = 0; j < s_currentHashFields.Length; j++)
			{
				if (s_currentHashFields[j] != null)
				{
					s_currentHashFields[j].SetValue(m_stand.m_visEquipment, -1);
				}
			}
		}
		ItemData val = null;
		ItemData val2 = null;
		ItemData val3 = null;
		ItemData val4 = null;
		ItemData val5 = null;
		ItemData val6 = null;
		ItemData itemAt = inventory.GetItemAt(0, row);
		ItemData itemAt2 = inventory.GetItemAt(1, row);
		ItemData itemAt3 = inventory.GetItemAt(2, row);
		ItemData itemAt4 = inventory.GetItemAt(3, row);
		ItemData itemAt5 = inventory.GetItemAt(4, row);
		ItemData itemAt6 = inventory.GetItemAt(5, row);
		if (itemAt != null && (int)itemAt.m_shared.m_itemType == 6)
		{
			val = itemAt;
		}
		if (itemAt2 != null && (int)itemAt2.m_shared.m_itemType == 7)
		{
			val2 = itemAt2;
		}
		if (itemAt3 != null && (int)itemAt3.m_shared.m_itemType == 11)
		{
			val3 = itemAt3;
		}
		if (itemAt4 != null && (int)itemAt4.m_shared.m_itemType == 5)
		{
			val4 = itemAt4;
		}
		if (itemAt5 != null && InventoryGrid_DropItem_Patch.IsItemValidForSlot(4, itemAt5))
		{
			val5 = itemAt5;
		}
		if (itemAt6 != null && (int)itemAt6.m_shared.m_itemType == 17)
		{
			val6 = itemAt6;
		}
		int width = inventory.GetWidth();
		for (int k = 0; k < width; k++)
		{
			ItemData itemAt7 = inventory.GetItemAt(k, row);
			if (itemAt7 != null)
			{
				ItemType itemType = itemAt7.m_shared.m_itemType;
				if (val == null && (int)itemType == 6)
				{
					val = itemAt7;
				}
				else if (val2 == null && (int)itemType == 7)
				{
					val2 = itemAt7;
				}
				else if (val3 == null && (int)itemType == 11)
				{
					val3 = itemAt7;
				}
				else if (val4 == null && (int)itemType == 5)
				{
					val4 = itemAt7;
				}
				else if (val5 == null && InventoryGrid_DropItem_Patch.IsItemValidForSlot(4, itemAt7))
				{
					val5 = itemAt7;
				}
				else if (val6 == null && (int)itemType == 17)
				{
					val6 = itemAt7;
				}
			}
		}
		ItemData[] array = (ItemData[])(object)new ItemData[6] { val, val2, val3, val4, val5, val6 };
		for (int l = 0; l < UI_COLUMN_SLOTS.Length; l++)
		{
			VisSlot targetSlot = UI_COLUMN_SLOTS[l];
			int standSlotIndexForVisSlot = GetStandSlotIndexForVisSlot(m_stand, targetSlot);
			ItemData val7 = array[l];
			string itemPrefabName = GetItemPrefabName(val7);
			int num = val7?.m_variant ?? 0;
			bool flag = val7 != null && InventoryGrid_DropItem_Patch.IsItemValidForSlot(l, val7, inventory, row);
			string text = ((flag && !string.IsNullOrEmpty(itemPrefabName)) ? itemPrefabName : "");
			int num2 = (flag ? num : 0);
			if (standSlotIndexForVisSlot >= 0 && standSlotIndexForVisSlot < itemKeyHashes.Length)
			{
				component.GetZDO().Set(itemKeyHashes[standSlotIndexForVisSlot], text);
				if (variantKeyHashes != null && standSlotIndexForVisSlot < variantKeyHashes.Length)
				{
					component.GetZDO().Set(variantKeyHashes[standSlotIndexForVisSlot], num2, false);
				}
				if (flag && val7 != null)
				{
					ItemDrop.SaveToZDO(standSlotIndexForVisSlot, val7, component.GetZDO());
				}
				if (s_setVisualItemMethod != null)
				{
					s_setVisualItemMethod.Invoke(m_stand, new object[3] { standSlotIndexForVisSlot, text, num2 });
				}
				component.InvokeRPC(ZRoutedRpc.Everybody, "RPC_SetVisualItem", new object[3] { standSlotIndexForVisSlot, text, num2 });
			}
		}
		ApplyWeaponStance(val5, val4);
		if ((Object)(object)m_stand.m_visEquipment != (Object)null && s_updateVisualsMethod != null)
		{
			s_updateVisualsMethod.Invoke(m_stand.m_visEquipment, null);
		}
		m_isSyncing = false;
	}

	public void UpdateStandVisualsChaos()
	{
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		if (m_isSyncing || (Object)(object)m_stand == (Object)null)
		{
			return;
		}
		List<Container> linkedChests = GetLinkedChests();
		if (linkedChests.Count == 0)
		{
			return;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return;
		}
		if (!component.IsOwner())
		{
			component.ClaimOwnership();
		}
		int[] itemKeyHashes = GetItemKeyHashes();
		int[] variantKeyHashes = GetVariantKeyHashes();
		if (itemKeyHashes == null)
		{
			return;
		}
		m_isSyncing = true;
		for (int i = 0; i < m_stand.m_slots.Count; i++)
		{
			if (m_stand.m_slots[i] != null)
			{
				m_stand.m_slots[i].m_visualName = null;
				m_stand.m_slots[i].m_visualVariant = -1;
			}
		}
		if ((Object)(object)m_stand.m_visEquipment != (Object)null)
		{
			for (int j = 0; j < s_currentHashFields.Length; j++)
			{
				if (s_currentHashFields[j] != null)
				{
					s_currentHashFields[j].SetValue(m_stand.m_visEquipment, -1);
				}
			}
		}
		ItemData randomItemInColumnAcrossChests = GetRandomItemInColumnAcrossChests(0);
		ItemData randomItemInColumnAcrossChests2 = GetRandomItemInColumnAcrossChests(1);
		ItemData randomItemInColumnAcrossChests3 = GetRandomItemInColumnAcrossChests(2);
		ItemData randomItemInColumnAcrossChests4 = GetRandomItemInColumnAcrossChests(3);
		ItemData randomItemInColumnAcrossChests5 = GetRandomItemInColumnAcrossChests(4);
		ItemData randomItemInColumnAcrossChests6 = GetRandomItemInColumnAcrossChests(5);
		ItemData[] array = (ItemData[])(object)new ItemData[6] { randomItemInColumnAcrossChests, randomItemInColumnAcrossChests2, randomItemInColumnAcrossChests3, randomItemInColumnAcrossChests4, randomItemInColumnAcrossChests5, randomItemInColumnAcrossChests6 };
		for (int k = 0; k < UI_COLUMN_SLOTS.Length; k++)
		{
			VisSlot targetSlot = UI_COLUMN_SLOTS[k];
			int standSlotIndexForVisSlot = GetStandSlotIndexForVisSlot(m_stand, targetSlot);
			ItemData val = array[k];
			string itemPrefabName = GetItemPrefabName(val);
			int num = val?.m_variant ?? 0;
			bool flag = val != null && InventoryGrid_DropItem_Patch.IsItemValidForSlot(k, val);
			string text = ((flag && !string.IsNullOrEmpty(itemPrefabName)) ? itemPrefabName : "");
			int num2 = (flag ? num : 0);
			if (standSlotIndexForVisSlot >= 0 && standSlotIndexForVisSlot < itemKeyHashes.Length)
			{
				component.GetZDO().Set(itemKeyHashes[standSlotIndexForVisSlot], text);
				if (variantKeyHashes != null && standSlotIndexForVisSlot < variantKeyHashes.Length)
				{
					component.GetZDO().Set(variantKeyHashes[standSlotIndexForVisSlot], num2, false);
				}
				if (s_setVisualItemMethod != null)
				{
					s_setVisualItemMethod.Invoke(m_stand, new object[3] { standSlotIndexForVisSlot, text, num2 });
				}
				component.InvokeRPC(ZRoutedRpc.Everybody, "RPC_SetVisualItem", new object[3] { standSlotIndexForVisSlot, text, num2 });
			}
		}
		ApplyWeaponStance(randomItemInColumnAcrossChests5, randomItemInColumnAcrossChests4);
		if ((Object)(object)m_stand.m_visEquipment != (Object)null && s_updateVisualsMethod != null)
		{
			s_updateVisualsMethod.Invoke(m_stand.m_visEquipment, null);
		}
		m_isSyncing = false;
	}

	private void ApplyWeaponStance(ItemData weaponItem, ItemData shieldItem)
	{
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return;
		}
		bool weaponsEquipped = GetWeaponsEquipped();
		bool flag = weaponItem != null && InventoryGrid_DropItem_Patch.IsTwoHandedWeapon(weaponItem);
		string itemPrefabName = GetItemPrefabName(weaponItem);
		string itemPrefabName2 = GetItemPrefabName(shieldItem);
		if (weaponsEquipped)
		{
			component.GetZDO().Set(ZDOVars.s_rightItem, (!string.IsNullOrEmpty(itemPrefabName)) ? StringExtensionMethods.GetStableHashCode(itemPrefabName) : 0, false);
			component.GetZDO().Set(ZDOVars.s_rightBackItem, 0, false);
			if (flag)
			{
				component.GetZDO().Set(ZDOVars.s_leftBackItem, (!string.IsNullOrEmpty(itemPrefabName2)) ? StringExtensionMethods.GetStableHashCode(itemPrefabName2) : 0, false);
				component.GetZDO().Set(ZDOVars.s_leftItem, 0, false);
			}
			else
			{
				component.GetZDO().Set(ZDOVars.s_leftItem, (!string.IsNullOrEmpty(itemPrefabName2)) ? StringExtensionMethods.GetStableHashCode(itemPrefabName2) : 0, false);
				component.GetZDO().Set(ZDOVars.s_leftBackItem, 0, false);
			}
		}
		else
		{
			component.GetZDO().Set(ZDOVars.s_rightItem, 0, false);
			component.GetZDO().Set(ZDOVars.s_leftItem, 0, false);
			component.GetZDO().Set(ZDOVars.s_rightBackItem, (!string.IsNullOrEmpty(itemPrefabName)) ? StringExtensionMethods.GetStableHashCode(itemPrefabName) : 0, false);
			component.GetZDO().Set(ZDOVars.s_leftBackItem, (!string.IsNullOrEmpty(itemPrefabName2)) ? StringExtensionMethods.GetStableHashCode(itemPrefabName2) : 0, false);
		}
	}

	private ItemData GetRandomItemInColumnAcrossChests(int col)
	{
		List<ItemData> list = new List<ItemData>();
		List<Container> linkedChests = GetLinkedChests();
		for (int i = 0; i < linkedChests.Count; i++)
		{
			Container val = linkedChests[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			Inventory inventory = val.GetInventory();
			if (inventory == null)
			{
				continue;
			}
			int height = inventory.GetHeight();
			int width = inventory.GetWidth();
			for (int j = 0; j < height; j++)
			{
				for (int k = 0; k < width; k++)
				{
					ItemData itemAt = inventory.GetItemAt(k, j);
					if (itemAt != null && InventoryGrid_DropItem_Patch.IsItemValidForSlot(col, itemAt, inventory, j))
					{
						list.Add(itemAt);
					}
				}
			}
		}
		if (list.Count == 0)
		{
			return null;
		}
		return list[Random.Range(0, list.Count)];
	}

	private bool SaveStandItemsToChest()
	{
		//IL_0195: 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_0264: Unknown result type (might be due to invalid IL or missing references)
		//IL_0269: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Unknown result type (might be due to invalid IL or missing references)
		List<Container> linkedChests = GetLinkedChests();
		if (linkedChests.Count == 0)
		{
			return false;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return false;
		}
		int[] itemKeyHashes = GetItemKeyHashes();
		int[] variantKeyHashes = GetVariantKeyHashes();
		if (itemKeyHashes == null)
		{
			return false;
		}
		bool flag = false;
		for (int i = 0; i < m_stand.m_slots.Count; i++)
		{
			if (!string.IsNullOrEmpty(component.GetZDO().GetString(itemKeyHashes[i], "")))
			{
				flag = true;
				break;
			}
		}
		if (!flag)
		{
			m_activeSetIndex = 0;
			return true;
		}
		if (!FindFirstEmptyChestRow(out var targetChest, out var targetRow))
		{
			Debug.Log((object)"[ArmorGallery] All linked chests are full — cannot save stand items.");
			if ((Object)(object)Player.m_localPlayer != (Object)null)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "Armor Gallery: All linked chests are full!", 0, (Sprite)null);
			}
			return false;
		}
		ZNetView component2 = ((Component)targetChest).GetComponent<ZNetView>();
		if ((Object)(object)component2 != (Object)null && component2.IsValid() && !component2.IsOwner())
		{
			component2.ClaimOwnership();
		}
		Inventory inventory = targetChest.GetInventory();
		if (inventory == null)
		{
			return false;
		}
		m_isSyncing = true;
		bool flag2 = false;
		for (int j = 0; j < UI_COLUMN_SLOTS.Length; j++)
		{
			VisSlot targetSlot = UI_COLUMN_SLOTS[j];
			int standSlotIndexForVisSlot = GetStandSlotIndexForVisSlot(m_stand, targetSlot);
			if (standSlotIndexForVisSlot < 0 || standSlotIndexForVisSlot >= itemKeyHashes.Length)
			{
				continue;
			}
			string text = component.GetZDO().GetString(itemKeyHashes[standSlotIndexForVisSlot], "");
			if (string.IsNullOrEmpty(text))
			{
				continue;
			}
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(text) : null);
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			ItemDrop component3 = val.GetComponent<ItemDrop>();
			if (!((Object)(object)component3 == (Object)null))
			{
				ItemData val2 = component3.m_itemData.Clone();
				ItemDrop.LoadFromZDO(standSlotIndexForVisSlot, val2, component.GetZDO());
				val2.m_gridPos = new Vector2i(j, targetRow);
				inventory.AddItem(val2, new Vector2i(j, targetRow));
				flag2 = true;
				component.GetZDO().Set(itemKeyHashes[standSlotIndexForVisSlot], "");
				if (variantKeyHashes != null && standSlotIndexForVisSlot < variantKeyHashes.Length)
				{
					component.GetZDO().Set(variantKeyHashes[standSlotIndexForVisSlot], 0, false);
				}
				Debug.Log((object)$"[ArmorGallery] Saved stand item '{text}' to chest row {targetRow}");
			}
		}
		m_isSyncing = false;
		if (flag2 && inventory.m_onChanged != null)
		{
			inventory.m_onChanged();
		}
		return true;
	}

	public bool GetWeaponsEquipped()
	{
		if ((Object)(object)m_stand == (Object)null)
		{
			return false;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		return (Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetBool("WeaponsEquipped", false);
	}

	public void ToggleWeaponsEquipped()
	{
		if ((Object)(object)m_stand == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && component.IsValid())
		{
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			bool flag = component.GetZDO().GetBool("WeaponsEquipped", false);
			component.GetZDO().Set("WeaponsEquipped", !flag);
			UpdateStandVisualsFromActiveRow();
		}
	}

	public void SetWeaponsEquipped(bool equipped)
	{
		if ((Object)(object)m_stand == (Object)null)
		{
			return;
		}
		ZNetView component = ((Component)m_stand).GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && component.IsValid())
		{
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			component.GetZDO().Set("WeaponsEquipped", equipped);
		}
	}

	public void SetRandomWeaponsEquipped()
	{
		bool weaponsEquipped = Random.value > 0.5f;
		SetWeaponsEquipped(weaponsEquipped);
	}
}
[HarmonyPatch(typeof(InventoryGui), "Show", new Type[]
{
	typeof(Container),
	typeof(int)
})]
public static class InventoryGui_Show_Patch
{
	public static void Postfix(InventoryGui __instance, Container container)
	{
		ArmorGalleryUI.OnShowContainer(__instance, container);
	}
}
[HarmonyPatch(typeof(InventoryGui), "Hide")]
public static class InventoryGui_Hide_Patch
{
	public static void Postfix(InventoryGui __instance)
	{
		ArmorGalleryUI.OnHideContainer(__instance);
	}
}
[HarmonyPatch(typeof(InventoryGui), "CloseContainer")]
public static class InventoryGui_CloseContainer_Patch
{
	public static void Postfix(InventoryGui __instance)
	{
		ArmorGalleryUI.OnHideContainer(__instance);
	}
}
[HarmonyPatch(typeof(InventoryGui), "UpdateContainer", new Type[] { typeof(Player) })]
public static class InventoryGui_UpdateContainer_Patch
{
	public static bool Prefix(InventoryGui __instance, Player player)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)__instance == (Object)null || (Object)(object)player == (Object)null)
		{
			return true;
		}
		Container val = ((!(ArmorGalleryUI.currentContainerField != null)) ? ((Container)null) : ((Container)ArmorGalleryUI.currentContainerField.GetValue(__instance)));
		if ((Object)(object)val != (Object)null)
		{
			ArmorStand linkedArmorStand = ArmorGalleryUI.GetLinkedArmorStand(val);
			if ((Object)(object)linkedArmorStand != (Object)null)
			{
				__instance.m_autoCloseDistance = ArmorGalleryPlugin.configMaxLinkDistance.Value + 5f;
				ZNetView component = ((Component)val).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid() && !component.IsOwner())
				{
					component.ClaimOwnership();
				}
			}
			else
			{
				__instance.m_autoCloseDistance = 4f;
			}
		}
		return true;
	}

	public static void Postfix(InventoryGui __instance, Player player)
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.m_container == (Object)null)
		{
			return;
		}
		Container val = ((!(ArmorGalleryUI.currentContainerField != null)) ? ((Container)null) : ((Container)ArmorGalleryUI.currentContainerField.GetValue(__instance)));
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		ArmorStand linkedArmorStand = ArmorGalleryUI.GetLinkedArmorStand(val);
		if ((Object)(object)linkedArmorStand == (Object)null)
		{
			return;
		}
		if ((Object)(object)ArmorGalleryUI.activeContainer != (Object)(object)val)
		{
			ArmorGalleryUI.OnShowContainer(__instance, val);
		}
		if ((Object)(object)ArmorGalleryUI.activeStand != (Object)null)
		{
			if (!ArmorGalleryUI.HasValidUIElements())
			{
				ArmorGalleryUI.InjectUI(__instance, val);
			}
			else
			{
				ArmorGalleryUI.EnforceGridTransform(__instance);
			}
		}
	}
}
[HarmonyPatch(typeof(InventoryGrid), "UpdateInventory", new Type[]
{
	typeof(Inventory),
	typeof(Player),
	typeof(ItemData)
})]
public static class InventoryGrid_UpdateInventory_Patch
{
	public static void Postfix(InventoryGrid __instance, Inventory inventory, Player player, ItemData dragItem)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		if ((Object)(object)InventoryGui.instance == (Object)null || (Object)(object)ArmorGalleryUI.activeContainer == (Object)null || (Object)(object)ArmorGalleryUI.activeStand == (Object)null)
		{
			return;
		}
		InventoryGrid val = (InventoryGrid)ArmorGalleryUI.containerGridField.GetValue(InventoryGui.instance);
		if (!((Object)(object)__instance != (Object)(object)val))
		{
			if (!ArmorGalleryUI.HasValidUIElements())
			{
				ArmorGalleryUI.InjectUI(InventoryGui.instance, ArmorGalleryUI.activeContainer);
			}
			else
			{
				ArmorGalleryUI.UpdateMisplacedSlotHighlights(InventoryGui.instance, ArmorGalleryUI.activeContainer);
			}
		}
	}
}
[HarmonyPatch(typeof(InventoryGrid), "DropItem")]
public static class InventoryGrid_DropItem_Patch
{
	public static bool Prefix(InventoryGrid __instance, Inventory fromInventory, ItemData item, int amount, Vector2i pos, ref bool __result)
	{
		Inventory inventory = __instance.GetInventory();
		if ((Object)(object)ArmorGalleryUI.activeStand != (Object)null && (Object)(object)ArmorGalleryUI.activeContainer != (Object)null && inventory != null)
		{
			ArmorGalleryRotator component = ((Component)ArmorGalleryUI.activeStand).GetComponent<ArmorGalleryRotator>();
			if ((Object)(object)component != (Object)null && component.IsChestLinked(ArmorGalleryUI.activeContainer) && ArmorGalleryUI.activeContainer.GetInventory() == inventory && !IsItemValidForSlot(pos.x, item, inventory, pos.y))
			{
				__result = false;
				return false;
			}
		}
		return true;
	}

	public static bool IsTwoHandedWeapon(ItemData item)
	{
		//IL_001c: 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_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_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Invalid comparison between Unknown and I4
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Invalid comparison between Unknown and I4
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Invalid comparison between Unknown and I4
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Invalid comparison between Unknown and I4
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Invalid comparison between Unknown and I4
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Invalid comparison between Unknown and I4
		if (item == null)
		{
			return false;
		}
		ItemType itemType = item.m_shared.m_itemType;
		ItemType attachOverride = item.m_shared.m_attachOverride;
		if ((int)itemType == 14 || (int)itemType == 22 || (int)itemType == 4 || (int)attachOverride == 4 || (int)attachOverride == 14 || (int)attachOverride == 22)
		{
			return true;
		}
		string text = ((item.m_shared.m_name != null) ? item.m_shared.m_name.ToLower() : "");
		string text2 = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name.ToLower() : "");
		if (text.Contains("bow") || text.Contains("crossbow") || text2.Contains("bow") || text2.Contains("crossbow") || text.Contains("dual") || text.Contains("berserker") || text2.Contains("early") || text2.Contains("dual"))
		{
			return true;
		}
		return false;
	}

	public static bool IsItemValidForSlot(int slotIndex, ItemData item, Inventory inv = null, int row = -1)
	{
		//IL_0016: 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_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Invalid comparison between Unknown and I4
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Invalid comparison between Unknown and I4
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Invalid comparison between Unknown and I4
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Invalid comparison between Unknown and I4
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Invalid comparison between Unknown and I4
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Invalid comparison between Unknown and I4
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Invalid comparison between Unknown and I4
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Invalid comparison between Unknown and I4
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Invalid comparison between Unknown and I4
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Invalid comparison between Unknown and I4
		if (item == null)
		{
			return true;
		}
		ItemType itemType = item.m_shared.m_itemType;
		return slotIndex switch
		{
			0 => (int)itemType == 6, 
			1 => (int)itemType == 7, 
			2 => (int)itemType == 11, 
			3 => (int)itemType == 5, 
			4 => (int)itemType == 3 || (int)itemType == 14 || (int)itemType == 22 || (int)itemType == 15 || (int)itemType == 4, 
			5 => (int)itemType == 17, 
			_ => true, 
		};
	}
}
[HarmonyPatch(typeof(Container), "Interact")]
public static class Container_Interact_Patch
{
	public static bool Prefix(Container __instance, Humanoid character, bool hold, bool alt, ref bool __result)
	{
		if ((Object)(object)ArmorGalleryRotator.s_activeLinkingStand != (Object)null)
		{
			ArmorGalleryRotator.s_activeLinkingStand.ToggleChestLink(__instance);
			__result = true;
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(Container), "GetHoverText")]
public static class Container_GetHoverText_Patch
{
	public static void Postfix(Container __instance, ref string __result)
	{
		if ((Object)(object)__instance == (Object)null || (Object)(object)ArmorGalleryRotator.s_activeLinkingStand == (Object)null)
		{
			return;
		}
		string useKeyName = ArmorGalleryPlugin.GetUseKeyName();
		if (ArmorGalleryRotator.s_activeLinkingStand.IsChestLinked(__instance))
		{
			__result += $"\n<color=#FF4444>[{useKeyName}] Unlink from Armor Stand</color>";
			return;
		}
		ArmorGalleryRotator rotatorLinkingChest = ArmorGalleryRotator.GetRotatorLinkingChest(__instance);
		if ((Object)(object)rotatorLinkingChest != (Object)null && (Object)(object)rotatorLinkingChest != (Object)(object)ArmorGalleryRotator.s_activeLinkingStand)
		{
			__result += "\n<color=#FFAA00>[Chest already linked to another Armor Stand]</color>";
		}
		else
		{
			__result += $"\n<color=#00FF00>[{useKeyName}] Link to Armor Stand</color>";
		}
	}
}
[HarmonyPatch(typeof(Container), "OnDestroyed")]
public static class Container_OnDestroyed_Patch
{
	public static void Prefix(Container __instance)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return;
		}
		foreach (ArmorGalleryRotator s_allRotator in ArmorGalleryRotator.s_allRotators)
		{
			if ((Object)(object)s_allRotator != (Object)null && s_allRotator.IsChestLinked(__instance))
			{
				s_allRotator.OnChestDestroyed(__instance);
			}
		}
	}
}
[HarmonyPatch(typeof(InventoryGui), "Update")]
public static class InventoryGui_Update_Patch
{
	public static void Postfix(InventoryGui __instance)
	{
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)__instance == (Object)null || !__instance.IsContainerOpen() || (Object)(object)ArmorGalleryUI.activeStand == (Object)null || (Object)(object)ArmorGalleryUI.activeContainer == (Object)null)
		{
			return;
		}
		ArmorGalleryRotator component = ((Component)ArmorGalleryUI.activeStand).GetComponent<ArmorGalleryRotator>();
		if ((Object)(object)component == (Object)null)
		{
			return;
		}
		List<Container> linkedChests = component.GetLinkedChests();
		if (linkedChests.Count <= 1)
		{
			return;
		}
		int num = linkedChests.IndexOf(ArmorGalleryUI.activeContainer);
		if (num < 0)
		{
			return;
		}
		if (Input.GetKeyDown(ArmorGalleryPlugin.configPrevChestKey.Value))
		{
			if (num > 0)
			{
				ZInput.ResetButtonStatus("Use");
				ZInput.ResetButtonStatus("JoyUse");
				ArmorGalleryUI.SwitchToContainer(__instance, linkedChests[num - 1]);
			}
		}
		else if (Input.GetKeyDown(ArmorGalleryPlugin.configNextChestKey.Value) && num < linkedChests.Count - 1)
		{
			ZInput.ResetButtonStatus("Use");
			ZInput.ResetButtonStatus("JoyUse");
			ArmorGalleryUI.SwitchToContainer(__instance, linkedChests[num + 1]);
		}
	}
}
public static class ArmorGalleryUI
{
	public static ArmorStand activeStand = null;

	public static List<GameObject> uiElements = new List<GameObject>();

	public static FieldInfo currentContainerField = typeof(InventoryGui).GetField("m_currentContainer", BindingFlags.Instance | BindingFlags.NonPublic);

	public static FieldInfo containerGridField = typeof(InventoryGui).GetField("m_containerGrid", BindingFlags.Instance | BindingFlags.NonPublic);

	private static FieldInfo firstContainerUpdateField = typeof(InventoryGui).GetField("m_firstContainerUpdate", BindingFlags.Instance | BindingFlags.NonPublic);

	private static FieldInfo gridWidthField = typeof(InventoryGrid).GetField("m_width", BindingFlags.Instance | BindingFlags.NonPublic);

	private static FieldInfo gridHeightField = typeof(InventoryGrid).GetField("m_height", BindingFlags.Instance | BindingFlags.NonPublic);

	private static FieldInfo elementsField = typeof(InventoryGrid).GetField("m_elements", BindingFlags.Instance | BindingFlags.NonPublic);

	private static FieldInfo elementGoField = null;

	public static Container activeContainer = null;

	private static bool s_gridScaled = false;

	private static Vector2 s_originalGridPos = Vector2.zero;

	private static MethodInfo updateContainerMethod = typeof(InventoryGui).GetMethod("UpdateContainer", BindingFlags.Instance | BindingFlags.NonPublic);

	private static FieldInfo rightItemField = typeof(Humanoid).GetField("m_rightItem", BindingFlags.Instance | BindingFlags.NonPublic);

	private static FieldInfo leftItemField = typeof(Humanoid).GetField("m_leftItem", BindingFlags.Instance | BindingFlags.NonPublic);

	public static void SwitchToContainer(InventoryGui gui, Container targetChest)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Expected O, but got Unknown
		if (!((Object)(object)gui == (Object)null) && !((Object)(object)targetChest == (Object)null))
		{
			Container val = (Container)currentContainerField.GetValue(gui);
			if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)targetChest)
			{
				val.SetInUse(false);
			}
			ZNetView component = ((Component)targetChest).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid() && !component.IsOwner())
			{
				component.ClaimOwnership();
			}
			targetChest.SetInUse(true);
			gui.m_autoCloseDistance = ArmorGalleryPlugin.configMaxLinkDistance.Value + 5f;
			if (firstContainerUpdateField != null)
			{
				firstContainerUpdateField.SetValue(gui, true);
			}
			currentContainerField.SetValue(gui, targetChest);
			if ((Object)(object)Player.m_localPlayer != (Object)null && updateContainerMethod != null)
			{
				updateContainerMethod.Invoke(gui, new object[1] { Player.m_localPlayer });
			}
			OnShowContainer(gui, targetChest);
		}
	}

	public static void OnShowContainer(InventoryGui gui, Container container)
	{
		OnHideContainer(gui);
		if ((Object)(object)container == (Object)null || (Object)(object)gui == (Object)null)
		{
			return;
		}
		activeStand = GetLinkedArmorStand(container);
		if (!((Object)(object)activeStand == (Object)null))
		{
			activeContainer = container;
			if (container.GetInventory() != null)
			{
				Inventory inventory = container.GetInventory();
				inventory.m_onChanged = (Action)Delegate.Combine(inventory.m_onChanged, new Action(OnInventoryChanged));
			}
			InjectUI(gui, container);
		}
	}

	public static bool HasValidUIElements()
	{
		if (uiElements == null || uiElements.Count == 0)
		{
			return false;
		}
		for (int i = 0; i < uiElements.Count; i++)
		{
			if ((Object)(object)uiElements[i] == (Object)null)
			{
				return false;
			}
		}
		return true;
	}

	public static void ClearUIElements()
	{
		if (uiElements == null)
		{
			return;
		}
		for (int i = 0; i < uiElements.Count; i++)
		{
			if ((Object)(object)uiElements[i] != (Object)null)
			{
				Object.Destroy((Object)(object)uiElements[i]);
			}
		}
		uiElements.Clear();
	}

	public static void OnHideContainer(InventoryGui gui = null)
	{
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Expected O, but got Unknown
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)activeContainer != (Object)null && activeContainer.GetInventory() != null)
		{
			Inventory inventory = activeContainer.GetInventory();
			inventory.m_onChanged = (Action)Delegate.Remove(inventory.m_onChanged, new Action(OnInventoryChanged));
		}
		activeContainer = null;
		activeStand = null;
		ClearUIElements();
		InventoryGui val = (((Object)(object)gui != (Object)null) ? gui : InventoryGui.instance);
		if (!((Object)(object)val != (Object)null))
		{
			return;
		}
		val.m_autoCloseDistance = 4f;
		if (s_gridScaled)
		{
			InventoryGrid val2 = (InventoryGrid)containerGridField.GetValue(val);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.m_gridRoot != (Object)null)
			{
				((Transform)val2.m_gridRoot).localScale = Vector3.one;
				val2.m_gridRoot.anchoredPosition = Vector2.zero;
			}
			s_gridScaled = false;
		}
	}

	public static void EnforceGridTransform(InventoryGui gui)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)gui == (Object)null)
		{
			return;
		}
		InventoryGrid val = (InventoryGrid)containerGridField.GetValue(gui);
		if (!((Object)(object)val == (Object)null) && !((Object)(object)val.m_gridRoot == (Object)null))
		{
			int num = (int)gridWidthField.GetValue(val);
			int num2 = (int)gridHeightField.GetValue(val);
			if (num2 >= 4 || num >= 8)
			{
				float num3 = ((num >= 8) ? 0.85f : 0.88f);
				float num4 = ((num >= 8) ? 38f : 20f);
				float num5 = -14f;
				((Transform)val.m_gridRoot).localScale = new Vector3(num3, num3, 1f);
				val.m_gridRoot.anchoredPosition = new Vector2(num4, num5);
				s_gridScaled = true;
			}
		}
	}

	private static void OnInventoryChanged()
	{
		if ((Object)(object)activeStand != (Object)null)
		{
			ArmorGalleryRotator component = ((Component)activeStand).GetComponent<ArmorGalleryRotator>();
			if ((Object)(object)component != (Object)null)
			{
				component.UpdateStandVisualsFromActiveRow();
			}
			if ((Object)(object)InventoryGui.instance != (Object)null && (Object)(object)activeContainer != (Object)null)
			{
				UpdateMisplacedSlotHighlights(InventoryGui.instance, activeContainer);
			}
		}
	}

	public static ArmorStand GetLinkedArmorStand(Container container)
	{
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)container == (Object)null)
		{
			return null;
		}
		if (container.GetInventory() != null && container.GetInventory().GetWidth() < 5)
		{
			return null;
		}
		if (((Object)container).name.ToLower().Contains("private") || ((Object)container).name.ToLower().Contains("personal"))
		{
			return null;
		}
		foreach (ArmorGalleryRotator s_allRotator in ArmorGalleryRotator.s_allRotators)
		{
			if ((Object)(object)s_allRotator != (Object)null && (Object)(object)s_allRotator.m_stand != (Object)null && s_allRotator.IsChestLinked(container))
			{
				return s_allRotator.m_stand;
			}
		}
		float num = ArmorGalleryPlugin.configMaxLinkDistance.Value + 2f;
		Collider[] array = Physics.OverlapSphere(((Component)container).transform.position, num);
		Collider[] array2 = array;
		foreach (Collider val in array2)
		{
			ArmorStand componentInParent = ((Component)val).GetComponentInParent<ArmorStand>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				ArmorGalleryRotator current = ((Component)componentInParent).GetComponent<ArmorGalleryRotator>();
				if ((Object)(object)current != (Object)null && current.IsChestLinked(container))
				{
					return componentInParent;
				}
			}
		}
		return null;
	}

	private static GameObject GetSlotGameObject(IList elements, int index)
	{
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		if (elements == null || index < 0 || index >= elements.Count)
		{
			return null;
		}
		object obj = elements[index];
		if (obj == null)
		{
			return null;
		}
		if (elementGoField == null)
		{
			elementGoField = obj.GetType().GetField("m_go", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		}
		if (elementGoField != null)
		{
			return (GameObject)elementGoField.GetValue(obj);
		}
		return null;
	}

	private static TextMeshProUGUI CreateTMPText(Transform parent, string name, TMP_FontAsset font)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
		val.SetActive(false);
		val.transform.SetParent(parent, false);
		TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
		if ((Object)(object)font != (Object)null)
		{
			((TMP_Text)val2).font = font;
		}
		val.SetActive(true);
		return val2;
	}

	public static void InjectUI(InventoryGui gui, Container container)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		//IL_0333: Unknown result type (might be due to invalid IL or missing references)
		//IL_033a: Expected O, but got Unknown
		//IL_0364: Unknown result type (might be due to invalid IL or missing references)
		//IL_037b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0392: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_041f: Unknown result type (might be due to invalid IL or missing references)
		//IL_042c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0439: Unknown result type (might be due to invalid IL or missing references)
		//IL_0446: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0506: Expected O, but got Unknown
		//IL_0564: Unknown result type (might be due to invalid IL or missing references)
		//IL_056b: Expected O, but got Unknown
		//IL_0595: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_05da: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_061b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0650: Unknown result type (might be due to invalid IL or missing references)
		//IL_065d: Unknown result type (might be due to invalid IL or missing references)
		//IL_066a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0677: Unknown result type (might be due to invalid IL or missing references)
		//IL_07c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d0: Expected O, but got Unknown
		//IL_07fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0811: Unknown result type (might be due to invalid IL or missing references)
		//IL_0828: Unknown result type (might be due to invalid IL or missing references)
		//IL_083f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0856: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_071a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0724: Expected O, but got Unknown
		//IL_08b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0898: Unknown result type (might be due to invalid IL or missing references)
		//IL_08df: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_08f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0906: Unknown result type (might be due to invalid IL or missing references)
		//IL_091d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0981: Unknown result type (might be due to invalid IL or missing references)
		//IL_0966: Unknown result type (might be due to invalid IL or missing references)
		//IL_0f9d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0fb4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0fcb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0fe2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ff9: Unknown result type (might be due to invalid IL or missing references)
		//IL_103c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e2d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e12: Unknown result type (might be due to invalid IL or missing references)
		//IL_10eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_10f2: Expected O, but got Unknown
		//IL_111c: Unknown result type (might be due to invalid IL or missing references)
		//IL_1133: Unknown result type (might be due to invalid IL or missing references)
		//IL_114a: Unknown result type (might be due to invalid IL or missing references)
		//IL_1161: Unknown result type (might be due to invalid IL or missing references)
		//IL_1178: Unknown result type (might be due to invalid IL or missing references)
		//IL_11a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_11cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_11da: Unknown result type (might be due to invalid IL or missing references)
		//IL_11e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_11f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_123c: Unknown result type (might be due to invalid IL or missing references)
		//IL_1271: Unknown result type (might be due to invalid IL or missing references)
		//IL_127b: Expected O, but got Unknown
		//IL_0a48: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a4f: Expected O, but got Unknown
		//IL_0a79: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a90: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aa7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0abe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ad5: Unknown result type (might be due to invalid IL or missing references)
		//IL_09df: Unknown result type (might be due to invalid IL or missing references)
		//IL_09e9: Expected O, but got Unknown
		//IL_0e33: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e66: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e7d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e94: Unknown result type (might be due to invalid IL or missing references)
		//IL_0eab: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ec2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ef3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b25: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b0a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b51: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b5e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b6b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b78: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b8f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bf3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bd8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c9d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0cb4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ccb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ce2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0cf9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d4c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c51: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c5b: Expected O, but got Unknown
		if (HasValidUIElements())
		{
			return;
		}
		ClearUIElements();
		InventoryGrid val = (InventoryGrid)containerGridField.GetValue(gui);
		if ((Object)(object)val == (Object)null || (Object)(object)gui.m_container == (Object)null)
		{
			return;
		}
		int num = (int)gridWidthField.GetValue(val);
		int num2 = (int)gridHeightField.GetValue(val);
		IList list = ((elementsField != null) ? ((IList)elementsField.GetValue(val)) : null);
		if (list == null || list.Count < num * num2)
		{
			return;
		}
		if (num2 >= 4 || num >= 8)
		{
			EnforceGridTransform(gui);
		}
		TMP_FontAsset font = (((Object)(object)gui.m_containerName != (Object)null) ? gui.m_containerName.font : null);
		ArmorGalleryRotator rotator = (((Object)(object)activeStand != (Object)null) ? ((Component)activeStand).GetComponent<ArmorGalleryRotator>() : null);
		List<Container> linkedChests = (((Object)(object)rotator != (Object)null) ? rotator.GetLinkedChests() : new List<Container> { container });
		int num3 = linkedChests.IndexOf(container);
		if (num3 < 0)
		{
			num3 = 0;
		}
		int num4 = 1;
		for (int