Decompiled source of ColorMe v1.0.1

ValheimArmorColors.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ValheimArmorColors")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ValheimArmorColors")]
[assembly: AssemblyTitle("ValheimArmorColors")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ValheimArmorColors
{
	public static class ArmorColorConfig
	{
		private static ConfigFile _cfg;

		public const string DefaultColor = "0,0,0,0";

		public static void Init(ConfigFile cfg)
		{
			_cfg = cfg;
		}

		public static string MakeKey(string charKey, string itemName)
		{
			return charKey + "::" + itemName;
		}

		public static Color GetColor(string charKey, string itemName)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<string> val = _cfg.Bind<string>("ItemColors", MakeKey(charKey, itemName), "0,0,0,0", (ConfigDescription)null);
			return Parse(val.Value);
		}

		public static void SetColor(string charKey, string itemName, Color color)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<string> val = _cfg.Bind<string>("ItemColors", MakeKey(charKey, itemName), "0,0,0,0", (ConfigDescription)null);
			val.Value = Serialize(color);
		}

		public static void ClearColor(string charKey, string itemName)
		{
			ConfigEntry<string> val = _cfg.Bind<string>("ItemColors", MakeKey(charKey, itemName), "0,0,0,0", (ConfigDescription)null);
			val.Value = "0,0,0,0";
		}

		public static Color Parse(string value)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			string[] array = value.Split(new char[1] { ',' });
			if (array.Length < 3)
			{
				return Color.clear;
			}
			float num = TryParse(array[0]);
			float num2 = TryParse(array[1]);
			float num3 = TryParse(array[2]);
			float num4 = ((array.Length >= 4) ? TryParse(array[3]) : 255f);
			return new Color(num / 255f, num2 / 255f, num3 / 255f, num4 / 255f);
		}

		public static string Serialize(Color c)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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)
			return $"{Mathf.RoundToInt(c.r * 255f)}," + $"{Mathf.RoundToInt(c.g * 255f)}," + $"{Mathf.RoundToInt(c.b * 255f)}," + $"{Mathf.RoundToInt(c.a * 255f)}";
		}

		private static float TryParse(string s)
		{
			float result;
			return float.TryParse(s.Trim(), out result) ? Mathf.Clamp(result, 0f, 255f) : 255f;
		}
	}
	[BepInPlugin("com.yourname.valheim.armorcolors", "ArmorColors", "1.0.0")]
	[BepInProcess("valheim.exe")]
	public class ArmorColorsPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.yourname.valheim.armorcolors";

		public const string PluginName = "ArmorColors";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			try
			{
				Log = ((BaseUnityPlugin)this).Logger;
				_harmony = new Harmony("com.yourname.valheim.armorcolors");
				_harmony.PatchAll();
				ArmorColorConfig.Init(((BaseUnityPlugin)this).Config);
				((Component)this).gameObject.AddComponent<ColorPickerUI>();
				((Component)this).gameObject.AddComponent<ArmorTintManager>();
				Log.LogInfo((object)"ArmorColors loaded. Numpad * = color picker, Numpad 0 = debug dump.");
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"[ArmorColorsPlugin] Failed to initialise: {arg}");
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public static class ArmorStandSync
	{
		private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private const string ZdoPrefix = "ArmorColor_";

		private static readonly string[] SlotNames = new string[5] { "helmet", "chest", "leg", "shoulder", "utility" };

		private static readonly string[] LegacySlotNames = new string[5] { "helmet", "chest", "legs", "cape", "utility" };

		private static readonly string[] ItemFields = new string[5] { "m_helmetItem", "m_chestItem", "m_legItem", "m_shoulderItem", "m_utilityItem" };

		public static void SetStandColor(ZNetView znv, string slot, Color color)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)znv == (Object)null) && znv.IsValid())
			{
				znv.GetZDO().Set("ArmorColor_" + slot, ColorUtility.ToHtmlStringRGBA(color));
			}
		}

		public static bool TryGetStandColor(ZNetView znv, string slot, out Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			color = Color.clear;
			if ((Object)(object)znv == (Object)null || !znv.IsValid())
			{
				return false;
			}
			string text = znv.GetZDO().GetString("ArmorColor_" + slot, "");
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			return ColorUtility.TryParseHtmlString("#" + text, ref color);
		}

		public static void ClearStandColor(ZNetView znv, string slot)
		{
			if (!((Object)(object)znv == (Object)null) && znv.IsValid())
			{
				znv.GetZDO().Set("ArmorColor_" + slot, "");
			}
		}

		public static void ApplyStandTints(VisEquipment ve, ZNetView znv)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)znv == (Object)null || !znv.IsValid())
			{
				return;
			}
			string charKey = $"stand_{znv.GetZDO().m_uid}";
			Type typeFromHandle = typeof(VisEquipment);
			for (int i = 0; i < SlotNames.Length; i++)
			{
				if ((TryGetStandColor(znv, SlotNames[i], out var color) && color.a != 0f) || (TryGetStandColor(znv, LegacySlotNames[i], out color) && color.a != 0f))
				{
					string text = typeFromHandle.GetField(ItemFields[i], Flags)?.GetValue(ve) as string;
					if (!string.IsNullOrEmpty(text))
					{
						ArmorColorConfig.SetColor(charKey, text, color);
					}
				}
			}
		}
	}
	public class ArmorTintManager : MonoBehaviour
	{
		private class TexState
		{
			public readonly Dictionary<string, Texture2D> Originals = new Dictionary<string, Texture2D>();

			public readonly Dictionary<string, Texture2D> Tinted = new Dictionary<string, Texture2D>();

			public readonly Dictionary<int, Material[]> RendererMats = new Dictionary<int, Material[]>();

			public string LastChestItem = null;

			public void Clear(MonoBehaviour owner)
			{
				foreach (Material[] value2 in RendererMats.Values)
				{
					if (value2 == null)
					{
						continue;
					}
					Material[] array = value2;
					foreach (Material val in array)
					{
						if ((Object)(object)val == (Object)null || !val.HasProperty("_MainTex"))
						{
							continue;
						}
						Texture texture = val.GetTexture("_MainTex");
						Texture2D val2 = (Texture2D)(object)((texture is Texture2D) ? texture : null);
						if ((Object)(object)val2 != (Object)null && ((Object)val2).name.StartsWith("tinted_"))
						{
							string key = ((Object)val2).name.Substring("tinted_".Length);
							if (Originals.TryGetValue(key, out Texture2D value) && Object.op_Implicit((Object)(object)value))
							{
								val.SetTexture("_MainTex", (Texture)(object)value);
							}
						}
					}
				}
				RendererMats.Clear();
				foreach (Texture2D value3 in Originals.Values)
				{
					if (Object.op_Implicit((Object)(object)value3))
					{
						owner.StartCoroutine(DestroyNextFrame((Object)(object)value3));
					}
				}
				foreach (Texture2D value4 in Tinted.Values)
				{
					if (Object.op_Implicit((Object)(object)value4))
					{
						owner.StartCoroutine(DestroyNextFrame((Object)(object)value4));
					}
				}
				Originals.Clear();
				Tinted.Clear();
				LastChestItem = null;
			}

			private static IEnumerator DestroyNextFrame(Object obj)
			{
				yield return null;
				if (Object.op_Implicit(obj))
				{
					Object.Destroy(obj);
				}
			}
		}

		private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly (string nameField, string instanceField, bool single)[] Slots = new(string, string, bool)[6]
		{
			("m_helmetItem", "m_helmetItemInstance", true),
			("m_chestItem", "m_chestItemInstances", false),
			("m_legItem", "m_legItemInstances", false),
			("m_shoulderItem", "m_shoulderItemInstances", false),
			("m_utilityItem", "m_utilityItemInstances", false),
			("m_trinketItem", "m_trinketItemInstances", false)
		};

		private readonly Dictionary<int, TexState> _texStates = new Dictionary<int, TexState>();

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

		private ArmorStand[] _cachedStands;

		private GameObject[] _cachedCompanions;

		private int _scanTimer = 0;

		private string _lastCharName = null;

		public static ArmorTintManager Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
		}

		private void OnEnable()
		{
			_lastCharName = null;
		}

		private void OnDestroy()
		{
			foreach (TexState value in _texStates.Values)
			{
				value.Clear((MonoBehaviour)(object)this);
			}
			_texStates.Clear();
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private TexState GetTexState(VisEquipment ve)
		{
			int instanceID = ((Object)ve).GetInstanceID();
			if (!_texStates.TryGetValue(instanceID, out TexState value))
			{
				value = (_texStates[instanceID] = new TexState());
			}
			return value;
		}

		private void LateUpdate()
		{
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				string playerName = localPlayer.GetPlayerName();
				if (!string.IsNullOrEmpty(playerName))
				{
					if (playerName != _lastCharName)
					{
						VisEquipment component = ((Component)localPlayer).GetComponent<VisEquipment>();
						if ((Object)(object)component != (Object)null)
						{
							int instanceID = ((Object)component).GetInstanceID();
							if (_texStates.TryGetValue(instanceID, out TexState value))
							{
								value.Clear((MonoBehaviour)(object)this);
								_texStates.Remove(instanceID);
							}
							_equipHashes.Remove(instanceID);
						}
						_lastCharName = playerName;
					}
					VisEquipment component2 = ((Component)localPlayer).GetComponent<VisEquipment>();
					if ((Object)(object)component2 != (Object)null)
					{
						ProcessVisEquipment(component2, ((Humanoid)localPlayer).GetInventory(), playerName);
					}
				}
			}
			_scanTimer++;
			if (_scanTimer >= 60)
			{
				_scanTimer = 0;
				_cachedStands = Object.FindObjectsOfType<ArmorStand>();
				List<GameObject> list = new List<GameObject>();
				ZNetView[] array = Object.FindObjectsOfType<ZNetView>();
				foreach (ZNetView val in array)
				{
					if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name == "HC_Companion(Clone)")
					{
						list.Add(((Component)val).gameObject);
					}
				}
				_cachedCompanions = list.ToArray();
				HashSet<int> hashSet = new HashSet<int>();
				if ((Object)(object)localPlayer != (Object)null)
				{
					VisEquipment component3 = ((Component)localPlayer).GetComponent<VisEquipment>();
					if ((Object)(object)component3 != (Object)null)
					{
						hashSet.Add(((Object)component3).GetInstanceID());
					}
				}
				if (_cachedStands != null)
				{
					ArmorStand[] cachedStands = _cachedStands;
					foreach (ArmorStand val2 in cachedStands)
					{
						if (!((Object)(object)val2 == (Object)null))
						{
							VisEquipment componentInChildren = ((Component)val2).GetComponentInChildren<VisEquipment>();
							if ((Object)(object)componentInChildren != (Object)null)
							{
								hashSet.Add(((Object)componentInChildren).GetInstanceID());
							}
						}
					}
				}
				if (_cachedCompanions != null)
				{
					GameObject[] cachedCompanions = _cachedCompanions;
					foreach (GameObject val3 in cachedCompanions)
					{
						if (!((Object)(object)val3 == (Object)null))
						{
							VisEquipment component4 = val3.GetComponent<VisEquipment>();
							if ((Object)(object)component4 != (Object)null)
							{
								hashSet.Add(((Object)component4).GetInstanceID());
							}
						}
					}
				}
				List<int> list2 = new List<int>();
				foreach (int key in _texStates.Keys)
				{
					if (!hashSet.Contains(key))
					{
						list2.Add(key);
					}
				}
				foreach (int item in list2)
				{
					_texStates[item].Clear((MonoBehaviour)(object)this);
					_texStates.Remove(item);
					_equipHashes.Remove(item);
				}
			}
			if (_cachedStands != null)
			{
				ArmorStand[] cachedStands2 = _cachedStands;
				foreach (ArmorStand val4 in cachedStands2)
				{
					if ((Object)(object)val4 == (Object)null)
					{
						continue;
					}
					ZNetView component5 = ((Component)val4).GetComponent<ZNetView>();
					if (!((Object)(object)component5 == (Object)null) && component5.IsValid())
					{
						VisEquipment componentInChildren2 = ((Component)val4).GetComponentInChildren<VisEquipment>();
						if (!((Object)(object)componentInChildren2 == (Object)null))
						{
							ArmorStandSync.ApplyStandTints(componentInChildren2, component5);
							ProcessVisEquipment(componentInChildren2, null, $"stand_{component5.GetZDO().m_uid}");
						}
					}
				}
			}
			if (_cachedCompanions == null)
			{
				return;
			}
			GameObject[] cachedCompanions2 = _cachedCompanions;
			foreach (GameObject val5 in cachedCompanions2)
			{
				if ((Object)(object)val5 == (Object)null)
				{
					continue;
				}
				ZNetView component6 = val5.GetComponent<ZNetView>();
				if (!((Object)(object)component6 == (Object)null) && component6.IsValid())
				{
					VisEquipment component7 = val5.GetComponent<VisEquipment>();
					if (!((Object)(object)component7 == (Object)null))
					{
						CompanionSync.SyncToConfig(component6);
						ProcessVisEquipment(component7, null, CompanionSync.GetCharKey(component6));
					}
				}
			}
		}

		private void ProcessVisEquipment(VisEquipment ve, Inventory inv, string charName)
		{
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04db: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			Type typeFromHandle = typeof(VisEquipment);
			int instanceID = ((Object)ve).GetInstanceID();
			bool flag = inv != null;
			string equipmentHash = GetEquipmentHash(ve, typeFromHandle);
			if (!_equipHashes.TryGetValue(instanceID, out string value) || equipmentHash != value)
			{
				if (_texStates.TryGetValue(instanceID, out TexState value2))
				{
					value2.Clear((MonoBehaviour)(object)this);
				}
				_texStates[instanceID] = new TexState();
				_equipHashes[instanceID] = equipmentHash;
			}
			TexState texState = GetTexState(ve);
			Dictionary<string, Color> dictionary = new Dictionary<string, Color>();
			(string, string, bool)[] slots = Slots;
			for (int i = 0; i < slots.Length; i++)
			{
				(string, string, bool) tuple = slots[i];
				string item = tuple.Item1;
				string item2 = tuple.Item2;
				bool item3 = tuple.Item3;
				string text = typeFromHandle.GetField(item, Flags)?.GetValue(ve) as string;
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				Color tint = GetTint(inv, charName, text);
				if (tint.a == 0f)
				{
					continue;
				}
				List<GameObject> list = new List<GameObject>();
				if (item3)
				{
					object? obj = typeFromHandle.GetField(item2, Flags)?.GetValue(ve);
					GameObject val = (GameObject)((obj is GameObject) ? obj : null);
					if ((Object)(object)val != (Object)null)
					{
						list.Add(val);
					}
				}
				else if (typeFromHandle.GetField(item2, Flags)?.GetValue(ve) is List<GameObject> collection)
				{
					list.AddRange(collection);
				}
				foreach (GameObject item4 in list)
				{
					if ((Object)(object)item4 == (Object)null)
					{
						continue;
					}
					Renderer[] componentsInChildren = item4.GetComponentsInChildren<Renderer>(true);
					foreach (Renderer val2 in componentsInChildren)
					{
						bool flag2 = ((object)val2).GetType().Name == "ParticleSystemRenderer";
						Material[] value3;
						if (flag && !flag2 && HasCreatureShader(val2))
						{
							int instanceID2 = ((Object)val2).GetInstanceID();
							if (!texState.RendererMats.TryGetValue(instanceID2, out value3))
							{
								value3 = val2.materials;
								texState.RendererMats[instanceID2] = value3;
							}
						}
						else
						{
							value3 = val2.materials;
						}
						Material[] array = value3;
						foreach (Material val3 in array)
						{
							if ((Object)(object)val3 == (Object)null)
							{
								continue;
							}
							if (flag2)
							{
								if (val3.HasProperty("_Color"))
								{
									val3.color = tint;
								}
								continue;
							}
							if (val3.HasProperty("_Color"))
							{
								val3.color = tint;
							}
							if (flag)
							{
								Shader shader = val3.shader;
								if (((shader != null) ? ((Object)shader).name : null) == "Custom/Creature")
								{
									TintMaterialTex(val3, "_MainTex", tint, texState);
								}
							}
							string key = StripSuffix(((Object)val3).name);
							if (!dictionary.ContainsKey(key))
							{
								dictionary[key] = tint;
							}
						}
					}
				}
			}
			if (dictionary.Count == 0)
			{
				return;
			}
			object? obj2 = typeFromHandle.GetField("m_visual", Flags)?.GetValue(ve);
			GameObject val4 = (GameObject)((obj2 is GameObject) ? obj2 : null);
			if ((Object)(object)val4 != (Object)null)
			{
				Renderer[] componentsInChildren2 = val4.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val5 in componentsInChildren2)
				{
					if (((object)val5).GetType().Name == "ParticleSystemRenderer")
					{
						continue;
					}
					Material[] sharedMaterials = val5.sharedMaterials;
					foreach (Material val6 in sharedMaterials)
					{
						if (!((Object)(object)val6 == (Object)null) && dictionary.TryGetValue(StripSuffix(((Object)val6).name), out var value4) && val6.HasProperty("_Color"))
						{
							val6.color = value4;
						}
					}
				}
			}
			if (!flag)
			{
				return;
			}
			string text2 = typeFromHandle.GetField("m_chestItem", Flags)?.GetValue(ve) as string;
			if (!string.IsNullOrEmpty(text2))
			{
				Color tint2 = GetTint(inv, charName, text2);
				if (tint2.a > 0f)
				{
					TintChestTex(ve, tint2, texState);
				}
			}
		}

		private Color GetTint(Inventory inv, string charName, string itemName)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			ItemData val = ((inv != null) ? FindItemInInventory(inv, itemName) : null);
			if (val != null && ItemColorSync.TryGetItemColor(val, out var color))
			{
				return color;
			}
			if (charName != null)
			{
				return ArmorColorConfig.GetColor(charName, itemName);
			}
			return Color.clear;
		}

		private static bool HasCreatureShader(Renderer r)
		{
			Material[] sharedMaterials = r.sharedMaterials;
			foreach (Material val in sharedMaterials)
			{
				if ((Object)(object)val != (Object)null)
				{
					Shader shader = val.shader;
					if (((shader != null) ? ((Object)shader).name : null) == "Custom/Creature")
					{
						return true;
					}
				}
			}
			return false;
		}

		private void TintChestTex(VisEquipment ve, Color tint, TexState state)
		{
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			object? obj = typeof(VisEquipment).GetField("m_bodyModel", Flags)?.GetValue(ve);
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)((obj is SkinnedMeshRenderer) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			string text = (typeof(VisEquipment).GetField("m_chestItem", Flags)?.GetValue(ve) as string) ?? "";
			if (text != state.LastChestItem)
			{
				Material[] materials = ((Renderer)val).materials;
				foreach (Material val2 in materials)
				{
					if ((Object)(object)val2 == (Object)null || !val2.HasProperty("_ChestTex"))
					{
						continue;
					}
					Texture texture = val2.GetTexture("_ChestTex");
					Texture2D val3 = (Texture2D)(object)((texture is Texture2D) ? texture : null);
					if (!((Object)(object)val3 == (Object)null) && ((Object)val3).name.StartsWith("tinted_"))
					{
						string key = ((Object)val3).name.Substring("tinted_".Length);
						if (state.Originals.TryGetValue(key, out Texture2D value) && Object.op_Implicit((Object)(object)value))
						{
							val2.SetTexture("_ChestTex", (Texture)(object)value);
						}
					}
				}
				state.Clear((MonoBehaviour)(object)this);
				state.LastChestItem = text;
			}
			Material[] materials2 = ((Renderer)val).materials;
			foreach (Material mat in materials2)
			{
				TintMaterialTex(mat, "_ChestTex", tint, state);
			}
		}

		private void TintMaterialTex(Material mat, string texProp, Color tint, TexState state)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			if (!mat.HasProperty(texProp) || tint == Color.white)
			{
				return;
			}
			Texture texture = mat.GetTexture(texProp);
			Texture2D val = (Texture2D)(object)((texture is Texture2D) ? texture : null);
			if ((Object)(object)val == (Object)null || string.IsNullOrEmpty(((Object)val).name))
			{
				return;
			}
			string text = ColorUtility.ToHtmlStringRGBA(tint);
			string text2 = ((Object)val).name;
			if (text2.StartsWith("tinted_"))
			{
				string text3 = text2.Substring("tinted_".Length);
				if (!state.Originals.ContainsKey(text3))
				{
					return;
				}
				string key = text3 + "|" + text;
				if (state.Tinted.TryGetValue(key, out Texture2D value) && Object.op_Implicit((Object)(object)value) && (Object)(object)mat.GetTexture(texProp) == (Object)(object)value)
				{
					return;
				}
				text2 = text3;
			}
			if (!state.Originals.ContainsKey(text2))
			{
				try
				{
					Texture2D val2 = GpuBlit(val);
					((Object)val2).name = text2;
					state.Originals[text2] = val2;
				}
				catch (Exception ex)
				{
					ArmorColorsPlugin.Log.LogError((object)("[ArmorTintManager] GpuBlit failed '" + text2 + "': " + ex.Message));
					return;
				}
			}
			string key2 = text2 + "|" + text;
			if (!state.Tinted.TryGetValue(key2, out Texture2D value2))
			{
				if (!state.Originals.TryGetValue(text2, out Texture2D value3))
				{
					return;
				}
				try
				{
					value2 = TintTexture(value3, tint);
					((Object)value2).name = "tinted_" + text2;
					state.Tinted[key2] = value2;
				}
				catch (Exception ex2)
				{
					ArmorColorsPlugin.Log.LogError((object)("[ArmorTintManager] TintTexture failed: " + ex2.Message));
					return;
				}
			}
			mat.SetTexture(texProp, (Texture)(object)value2);
		}

		private static Texture2D GpuBlit(Texture2D source)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)source).width, ((Texture)source).height, 0, (RenderTextureFormat)0);
			RenderTexture active = RenderTexture.active;
			Graphics.Blit((Texture)(object)source, temporary);
			RenderTexture.active = temporary;
			Texture2D val = new Texture2D(((Texture)source).width, ((Texture)source).height, (TextureFormat)5, false);
			val.ReadPixels(new Rect(0f, 0f, (float)((Texture)source).width, (float)((Texture)source).height), 0, 0);
			val.Apply();
			RenderTexture.active = active;
			RenderTexture.ReleaseTemporary(temporary);
			return val;
		}

		private static Texture2D TintTexture(Texture2D source, Color tint)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = GpuBlit(source);
			Color[] pixels = val.GetPixels();
			float num = 0.299f * tint.r + 0.587f * tint.g + 0.114f * tint.b;
			for (int i = 0; i < pixels.Length; i++)
			{
				Color val2 = pixels[i];
				float num2 = 0.299f * val2.r + 0.587f * val2.g + 0.114f * val2.b;
				float num3 = ((num > 0.001f) ? (num2 / num) : 0f);
				pixels[i] = new Color(Mathf.Clamp01(tint.r * num3), Mathf.Clamp01(tint.g * num3), Mathf.Clamp01(tint.b * num3), val2.a);
			}
			val.SetPixels(pixels);
			val.Apply();
			return val;
		}

		private static string StripSuffix(string name)
		{
			int num = name.IndexOf(" (Instance)");
			return (num >= 0) ? name.Substring(0, num) : name;
		}

		private static string GetEquipmentHash(VisEquipment ve, Type veType)
		{
			StringBuilder stringBuilder = new StringBuilder();
			string[] array = new string[6] { "m_helmetItem", "m_chestItem", "m_legItem", "m_shoulderItem", "m_utilityItem", "m_trinketItem" };
			foreach (string name in array)
			{
				string value = (veType.GetField(name, Flags)?.GetValue(ve) as string) ?? "";
				stringBuilder.Append(value).Append('|');
			}
			stringBuilder.Append(((Object)ve).GetInstanceID());
			return stringBuilder.ToString();
		}

		private static ItemData FindItemInInventory(Inventory inv, string itemName)
		{
			if (inv == null)
			{
				return null;
			}
			foreach (ItemData allItem in inv.GetAllItems())
			{
				if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name.Equals(itemName, StringComparison.OrdinalIgnoreCase))
				{
					return allItem;
				}
			}
			return null;
		}
	}
	public class ColorPickerUI : MonoBehaviour
	{
		private struct EquippedItem
		{
			public string SlotLabel;

			public string ItemName;

			public string DisplayName;

			public string SlotKey;
		}

		private bool _visible = false;

		private Rect _windowRect = new Rect(0f, 0f, 380f, 560f);

		private bool _windowPositioned = false;

		private KeyCode _toggleKey = (KeyCode)268;

		private List<EquippedItem> _items = new List<EquippedItem>();

		private int _selectedIndex = -1;

		private string _lastEquipHash = "";

		private ZNetView _targetCompanion = null;

		private VisEquipment _targetCompanionVE = null;

		private string _targetCompanionName = "";

		private Color _editColor = Color.white;

		private Color _savedColor = Color.white;

		private string _hexInput = "FFFFFFFF";

		private bool _hexDirty = false;

		private GUIStyle _selectedStyle;

		private GUIStyle _swatchStyle;

		private GUIStyle _hexFieldStyle;

		private GUIStyle _headerStyle;

		private Texture2D _selectedTex;

		private Texture2D _swatchTex;

		private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly MethodInfo _updateVisualsMethod = typeof(VisEquipment).GetMethod("UpdateLodgroup", Flags);

		private static readonly (string label, string field)[] SlotDefs = new(string, string)[6]
		{
			("Helmet", "m_helmetItem"),
			("Chest", "m_chestItem"),
			("Legs", "m_legItem"),
			("Cape", "m_shoulderItem"),
			("Utility", "m_utilityItem"),
			("Trinket", "m_trinketItem")
		};

		private void Update()
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Input.GetKeyDown(_toggleKey))
				{
					_visible = !_visible;
					if (_visible)
					{
						_windowPositioned = false;
						RefreshEquippedItems();
					}
				}
				if (_visible)
				{
					string equipHash = GetEquipHash();
					if (equipHash != _lastEquipHash)
					{
						RefreshEquippedItems();
					}
				}
			}
			catch (Exception arg)
			{
				ArmorColorsPlugin.Log.LogError((object)$"[ColorPickerUI.Update] {arg}");
			}
		}

		private void OnGUI()
		{
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			if (!_visible)
			{
				return;
			}
			if (!_windowPositioned)
			{
				((Rect)(ref _windowRect)).x = (float)Screen.width / 2f - ((Rect)(ref _windowRect)).width / 2f;
				((Rect)(ref _windowRect)).y = (float)Screen.height / 2f - ((Rect)(ref _windowRect)).height / 2f;
				_windowPositioned = true;
			}
			try
			{
				if (_selectedStyle == null)
				{
					BuildStyles();
				}
				string text = (((Object)(object)Player.m_localPlayer != (Object)null) ? VisEquipmentPatch.GetCharacterName(Player.m_localPlayer) : "");
				string text2 = (((Object)(object)_targetCompanion != (Object)null) ? ("  ⚔  Coloring: " + _targetCompanionName) : (string.IsNullOrEmpty(text) ? "  ⚔  Armor Colors" : ("  ⚔  " + text + "'s Armor Colors")));
				_windowRect = GUI.Window(0, _windowRect, new WindowFunction(DrawWindow), text2);
			}
			catch (Exception arg)
			{
				ArmorColorsPlugin.Log.LogError((object)$"[ColorPickerUI.OnGUI] {arg}");
				_visible = false;
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_selectedTex != (Object)null)
			{
				Object.Destroy((Object)(object)_selectedTex);
			}
			if ((Object)(object)_swatchTex != (Object)null)
			{
				Object.Destroy((Object)(object)_swatchTex);
			}
		}

		private void DrawWindow(int id)
		{
			//IL_0688: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Invalid comparison between Unknown and I4
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Invalid comparison between Unknown and I4
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0520: Unknown result type (might be due to invalid IL or missing references)
			//IL_054c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0568: Unknown result type (might be due to invalid IL or missing references)
			//IL_056b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_057d: Unknown result type (might be due to invalid IL or missing references)
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0586: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Space(6f);
			GUILayout.Label("EQUIPPED ITEMS", _headerStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(2f);
			if (_items.Count == 0)
			{
				GUILayout.Label("  No armor equipped.", Array.Empty<GUILayoutOption>());
			}
			else
			{
				Player localPlayer = Player.m_localPlayer;
				string charKey = (((Object)(object)_targetCompanion != (Object)null) ? CompanionSync.GetCharKey(_targetCompanion) : (((Object)(object)localPlayer != (Object)null) ? VisEquipmentPatch.GetCharacterName(localPlayer) : ""));
				for (int i = 0; i < _items.Count; i++)
				{
					EquippedItem equippedItem = _items[i];
					GUIStyle val = (GUIStyle)((i == _selectedIndex) ? ((object)_selectedStyle) : ((object)GUI.skin.button));
					Color color = ArmorColorConfig.GetColor(charKey, equippedItem.ItemName);
					string text = ((color.a > 0f) ? "● " : "○ ");
					if (GUILayout.Button(text + "[" + equippedItem.SlotLabel + "]  " + equippedItem.DisplayName, val, Array.Empty<GUILayoutOption>()))
					{
						SelectItem(i);
					}
				}
			}
			GUILayout.Space(10f);
			if (_selectedIndex >= 0 && _selectedIndex < _items.Count)
			{
				GUILayout.Label("EDITING: " + _items[_selectedIndex].DisplayName.ToUpper(), _headerStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Space(6f);
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label("HEX", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(36f) });
				GUILayout.Label("#", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(12f) });
				GUI.SetNextControlName("HexField");
				string text2 = GUILayout.TextField(_hexInput, 8, _hexFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
				if (text2 != _hexInput)
				{
					_hexInput = text2.ToUpper();
					_hexDirty = true;
					Color editColor = default(Color);
					if ((text2.Length == 6 || text2.Length == 8) && ColorUtility.TryParseHtmlString("#" + text2, ref editColor))
					{
						_editColor = editColor;
						_hexDirty = false;
					}
				}
				if ((int)Event.current.type == 4 && (int)Event.current.keyCode == 13 && GUI.GetNameOfFocusedControl() == "HexField")
				{
					Color editColor2 = default(Color);
					if (ColorUtility.TryParseHtmlString("#" + _hexInput, ref editColor2))
					{
						_editColor = editColor2;
						_hexDirty = false;
					}
					Event.current.Use();
				}
				GUILayout.FlexibleSpace();
				GUILayout.EndHorizontal();
				GUILayout.Space(8f);
				GUILayout.Label("PREVIEW", _headerStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Space(2f);
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				Color color2 = GUI.color;
				GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) });
				GUILayout.Label("New", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) });
				GUI.color = _editColor;
				GUILayout.Box(GUIContent.none, _swatchStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(160f),
					GUILayout.Height(50f)
				});
				GUI.color = color2;
				GUILayout.EndVertical();
				GUILayout.Space(8f);
				GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) });
				GUILayout.Label("Saved", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) });
				GUI.color = _savedColor;
				GUILayout.Box(GUIContent.none, _swatchStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(160f),
					GUILayout.Height(50f)
				});
				GUI.color = color2;
				GUILayout.EndVertical();
				GUILayout.EndHorizontal();
				GUILayout.Space(8f);
				GUILayout.Label("SLIDERS", _headerStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Space(2f);
				SliderRow("R", _editColor.r, new Color(1f, 0f, 0f), out var newValue);
				SliderRow("G", _editColor.g, new Color(0f, 1f, 0f), out var newValue2);
				SliderRow("B", _editColor.b, new Color(0f, 0f, 1f), out var newValue3);
				SliderRow("A", _editColor.a, new Color(1f, 1f, 1f), out var newValue4);
				Color val2 = default(Color);
				((Color)(ref val2))..ctor(newValue, newValue2, newValue3, newValue4);
				if (val2 != _editColor)
				{
					_editColor = val2;
					_hexInput = ColorUtility.ToHtmlStringRGBA(_editColor);
					_hexDirty = false;
				}
				GUILayout.Space(10f);
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Apply", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
				{
					ApplyColor();
				}
				if (GUILayout.Button("Reset to Default", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
				{
					ResetColor();
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.FlexibleSpace();
			GUILayout.Space(4f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Numpad * to toggle", GUI.skin.box, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Refresh", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
			{
				RefreshEquippedItems();
			}
			GUILayout.EndHorizontal();
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f));
		}

		private void RefreshEquippedItems()
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			_items.Clear();
			_selectedIndex = -1;
			_targetCompanion = null;
			_targetCompanionVE = null;
			_targetCompanionName = "";
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			float num = 5f;
			ZNetView[] array = Object.FindObjectsOfType<ZNetView>();
			foreach (ZNetView val in array)
			{
				if (!((Object)(object)val == (Object)null) && val.IsValid() && !(((Object)((Component)val).gameObject).name != "HC_Companion(Clone)"))
				{
					float num2 = Vector3.Distance(((Component)localPlayer).transform.position, ((Component)val).transform.position);
					if (num2 < num)
					{
						num = num2;
						_targetCompanion = val;
						_targetCompanionVE = ((Component)val).GetComponent<VisEquipment>();
						_targetCompanionName = val.GetZDO().GetString("HC_Name", ((Object)((Component)val).gameObject).name);
					}
				}
			}
			VisEquipment obj;
			if ((Object)(object)_targetCompanion != (Object)null && (Object)(object)_targetCompanionVE != (Object)null)
			{
				obj = _targetCompanionVE;
				string charKey = CompanionSync.GetCharKey(_targetCompanion);
				ArmorColorsPlugin.Log.LogInfo((object)("[ColorPickerUI] Targeting companion " + _targetCompanionName));
			}
			else
			{
				obj = ((Component)localPlayer).GetComponent<VisEquipment>();
				string charKey = VisEquipmentPatch.GetCharacterName(localPlayer);
				if (charKey == null)
				{
					return;
				}
			}
			Type typeFromHandle = typeof(VisEquipment);
			(string, string)[] slotDefs = SlotDefs;
			for (int j = 0; j < slotDefs.Length; j++)
			{
				(string, string) tuple = slotDefs[j];
				string item = tuple.Item1;
				string item2 = tuple.Item2;
				string text = typeFromHandle.GetField(item2, Flags)?.GetValue(obj) as string;
				if (!string.IsNullOrEmpty(text))
				{
					_items.Add(new EquippedItem
					{
						SlotLabel = item,
						ItemName = text,
						DisplayName = Prettify(text),
						SlotKey = item2.Replace("m_", "").Replace("Item", "")
					});
				}
			}
			ArmorColorsPlugin.Log.LogInfo((object)$"[ColorPickerUI] Found {_items.Count} equipped item(s).");
			_lastEquipHash = GetEquipHash();
		}

		private void SelectItem(int index)
		{
			//IL_005a: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			_selectedIndex = index;
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				string text = (((Object)(object)_targetCompanion != (Object)null) ? CompanionSync.GetCharKey(_targetCompanion) : VisEquipmentPatch.GetCharacterName(localPlayer));
				if (text != null)
				{
					_editColor = ArmorColorConfig.GetColor(text, _items[index].ItemName);
					_savedColor = _editColor;
					_hexInput = ColorUtility.ToHtmlStringRGBA(_editColor);
					_hexDirty = false;
				}
			}
		}

		private void ApplyColor()
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || _selectedIndex < 0)
			{
				return;
			}
			string itemName = _items[_selectedIndex].ItemName;
			string slotKey = _items[_selectedIndex].SlotKey;
			if ((Object)(object)_targetCompanion != (Object)null && (Object)(object)_targetCompanionVE != (Object)null)
			{
				string charKey = CompanionSync.GetCharKey(_targetCompanion);
				ArmorColorConfig.SetColor(charKey, itemName, _editColor);
				CompanionSync.SetColor(_targetCompanion, slotKey, _editColor);
				_updateVisualsMethod?.Invoke(_targetCompanionVE, null);
				ArmorColorsPlugin.Log.LogInfo((object)("[ColorPickerUI] Applied " + slotKey + " to companion " + _targetCompanionName));
			}
			else
			{
				string characterName = VisEquipmentPatch.GetCharacterName(localPlayer);
				if (characterName == null)
				{
					return;
				}
				ArmorColorConfig.SetColor(characterName, itemName, _editColor);
				ItemData val = FindEquippedItem(localPlayer, itemName);
				if (val != null)
				{
					ItemColorSync.SetItemColor(val, _editColor);
				}
				ItemColorSync.BroadcastColor(localPlayer, itemName, _editColor);
				ApplyToNearbyStand(slotKey, _editColor);
				_updateVisualsMethod?.Invoke(((Component)localPlayer).GetComponent<VisEquipment>(), null);
				ArmorColorsPlugin.Log.LogInfo((object)("[ColorPickerUI] Saved color for " + characterName + "::" + itemName));
			}
			_savedColor = _editColor;
		}

		private void ResetColor()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || _selectedIndex < 0)
			{
				return;
			}
			string itemName = _items[_selectedIndex].ItemName;
			string slotKey = _items[_selectedIndex].SlotKey;
			if ((Object)(object)_targetCompanion != (Object)null && (Object)(object)_targetCompanionVE != (Object)null)
			{
				string charKey = CompanionSync.GetCharKey(_targetCompanion);
				ArmorColorConfig.ClearColor(charKey, itemName);
				CompanionSync.SetColor(_targetCompanion, slotKey, Color.clear);
				_updateVisualsMethod?.Invoke(_targetCompanionVE, null);
			}
			else
			{
				string characterName = VisEquipmentPatch.GetCharacterName(localPlayer);
				if (characterName == null)
				{
					return;
				}
				ArmorColorConfig.ClearColor(characterName, itemName);
				ItemData val = FindEquippedItem(localPlayer, itemName);
				if (val != null)
				{
					ItemColorSync.ClearItemColor(val);
				}
				ItemColorSync.BroadcastReset(localPlayer, itemName);
				ApplyToNearbyStand(slotKey, Color.clear);
				_updateVisualsMethod?.Invoke(((Component)localPlayer).GetComponent<VisEquipment>(), null);
			}
			_editColor = Color.white;
			_savedColor = Color.white;
			_hexInput = "FFFFFFFF";
		}

		private static void ApplyToNearbyStand(string slotKey, Color color)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			ArmorStand val = null;
			float num = 5f;
			ArmorStand[] array = Object.FindObjectsOfType<ArmorStand>();
			foreach (ArmorStand val2 in array)
			{
				float num2 = Vector3.Distance(((Component)localPlayer).transform.position, ((Component)val2).transform.position);
				if (num2 < num)
				{
					num = num2;
					val = val2;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)val).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return;
			}
			if (color.a == 0f)
			{
				ArmorStandSync.ClearStandColor(component, slotKey);
			}
			else
			{
				ArmorStandSync.SetStandColor(component, slotKey, color);
			}
			string charKey = $"stand_{component.GetZDO().m_uid}";
			VisEquipment componentInChildren = ((Component)val).GetComponentInChildren<VisEquipment>();
			if (!((Object)(object)componentInChildren != (Object)null))
			{
				return;
			}
			string text = typeof(VisEquipment).GetField("m_" + slotKey + "Item", Flags)?.GetValue(componentInChildren) as string;
			if (!string.IsNullOrEmpty(text))
			{
				if (color.a == 0f)
				{
					ArmorColorConfig.ClearColor(charKey, text);
				}
				else
				{
					ArmorColorConfig.SetColor(charKey, text, color);
				}
			}
		}

		private static void SliderRow(string label, float value, Color labelColor, out float newValue)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			Color contentColor = GUI.contentColor;
			GUI.contentColor = labelColor;
			GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(16f) });
			GUI.contentColor = contentColor;
			newValue = GUILayout.HorizontalSlider(value, 0f, 1f, Array.Empty<GUILayoutOption>());
			GUILayout.Label(Mathf.RoundToInt(newValue * 255f).ToString("D3"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) });
			GUILayout.EndHorizontal();
		}

		private void BuildStyles()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			_selectedTex = MakeTex(new Color(0.2f, 0.5f, 1f, 0.7f));
			_selectedStyle = new GUIStyle(GUI.skin.button)
			{
				fontStyle = (FontStyle)1
			};
			_selectedStyle.normal.background = _selectedTex;
			_selectedStyle.hover.background = _selectedTex;
			_swatchTex = MakeTex(Color.white);
			GUIStyle val = new GUIStyle(GUI.skin.box);
			val.normal.background = _swatchTex;
			_swatchStyle = val;
			_hexFieldStyle = new GUIStyle(GUI.skin.textField)
			{
				fontSize = 14,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)3
			};
			_headerStyle = new GUIStyle(GUI.skin.label)
			{
				fontStyle = (FontStyle)1,
				fontSize = 10
			};
			_headerStyle.normal.textColor = new Color(0.7f, 0.85f, 1f);
		}

		private static Texture2D MakeTex(Color col)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(2, 2);
			val.SetPixels((Color[])(object)new Color[4] { col, col, col, col });
			val.Apply();
			return val;
		}

		private string GetEquipHash()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return "";
			}
			VisEquipment component = ((Component)localPlayer).GetComponent<VisEquipment>();
			StringBuilder stringBuilder = new StringBuilder();
			Type typeFromHandle = typeof(VisEquipment);
			(string, string)[] slotDefs = SlotDefs;
			for (int i = 0; i < slotDefs.Length; i++)
			{
				string item = slotDefs[i].Item2;
				string value = (typeFromHandle.GetField(item, Flags)?.GetValue(component) as string) ?? "";
				stringBuilder.Append(value).Append('|');
			}
			return stringBuilder.ToString();
		}

		private static ItemData FindEquippedItem(Player player, string itemName)
		{
			foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems())
			{
				if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name.Equals(itemName, StringComparison.OrdinalIgnoreCase))
				{
					return allItem;
				}
			}
			return null;
		}

		private static string Prettify(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return raw;
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(raw[0]);
			for (int i = 1; i < raw.Length; i++)
			{
				if (char.IsUpper(raw[i]) && !char.IsUpper(raw[i - 1]))
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(raw[i]);
			}
			return stringBuilder.ToString();
		}
	}
	public static class CompanionSync
	{
		private static readonly BindingFlags BF = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private const string ZdoPrefix = "ArmorColor_";

		private static readonly string[] Slots = new string[5] { "helmet", "chest", "leg", "shoulder", "utility" };

		public static void SetColor(ZNetView znv, string slot, Color color)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)znv == (Object)null) && znv.IsValid())
			{
				znv.GetZDO().Set("ArmorColor_" + slot, ColorUtility.ToHtmlStringRGBA(color));
			}
		}

		public static bool TryGetColor(ZNetView znv, string slot, out Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			color = Color.white;
			if ((Object)(object)znv == (Object)null || !znv.IsValid())
			{
				return false;
			}
			string text = znv.GetZDO().GetString("ArmorColor_" + slot, "");
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			return ColorUtility.TryParseHtmlString("#" + text, ref color);
		}

		public unsafe static string GetCharKey(ZNetView znv)
		{
			//IL_0029: 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)
			if ((Object)(object)znv == (Object)null || !znv.IsValid())
			{
				return null;
			}
			ZDOID uid = znv.GetZDO().m_uid;
			return "companion_" + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
		}

		public static void SyncToConfig(ZNetView znv)
		{
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)znv == (Object)null || !znv.IsValid())
			{
				return;
			}
			string charKey = GetCharKey(znv);
			VisEquipment component = ((Component)znv).GetComponent<VisEquipment>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			Dictionary<string, string> slotItems = GetSlotItems(component);
			string[] slots = Slots;
			foreach (string text in slots)
			{
				if (slotItems.TryGetValue(text, out var value) && !string.IsNullOrEmpty(value) && TryGetColor(znv, text, out var color))
				{
					ArmorColorConfig.SetColor(charKey, value, color);
				}
			}
		}

		public static Dictionary<string, string> GetSlotItems(VisEquipment ve)
		{
			Type typeFromHandle = typeof(VisEquipment);
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			dictionary["helmet"] = (typeFromHandle.GetField("m_helmetItem", BF)?.GetValue(ve) as string) ?? "";
			dictionary["chest"] = (typeFromHandle.GetField("m_chestItem", BF)?.GetValue(ve) as string) ?? "";
			dictionary["leg"] = (typeFromHandle.GetField("m_legItem", BF)?.GetValue(ve) as string) ?? "";
			dictionary["shoulder"] = (typeFromHandle.GetField("m_shoulderItem", BF)?.GetValue(ve) as string) ?? "";
			dictionary["utility"] = (typeFromHandle.GetField("m_utilityItem", BF)?.GetValue(ve) as string) ?? "";
			return dictionary;
		}
	}
	public static class ItemColorSync
	{
		[HarmonyPatch(typeof(Player), "Awake")]
		public static class PlayerAwakePatch
		{
			[HarmonyPostfix]
			private static void Postfix(Player __instance)
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				component.Register<string>("ArmorColors_Sync", (Action<long, string>)delegate(long sender, string payload)
				{
					//IL_008c: Unknown result type (might be due to invalid IL or missing references)
					try
					{
						if (!((Object)(object)__instance == (Object)(object)Player.m_localPlayer))
						{
							string[] array = payload.Split(new char[1] { '|' });
							if (array.Length == 2)
							{
								string itemName = array[0];
								string text = array[1];
								string playerName = __instance.GetPlayerName();
								Color color = default(Color);
								if (text == "RESET")
								{
									ArmorColorConfig.ClearColor(playerName, itemName);
								}
								else if (ColorUtility.TryParseHtmlString("#" + text, ref color))
								{
									ArmorColorConfig.SetColor(playerName, itemName, color);
								}
								VisEquipment component2 = ((Component)__instance).GetComponent<VisEquipment>();
								typeof(VisEquipment).GetMethod("UpdateLodgroup", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(component2, null);
							}
						}
					}
					catch (Exception ex)
					{
						ArmorColorsPlugin.Log.LogError((object)("[ItemColorSync] RPC error: " + ex.Message));
					}
				});
			}
		}

		private const string CustomDataKey = "ArmorColor";

		private const string RpcName = "ArmorColors_Sync";

		public static bool TryGetItemColor(ItemData item, out Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			color = Color.white;
			if (item?.m_customData == null)
			{
				return false;
			}
			if (!item.m_customData.TryGetValue("ArmorColor", out var value))
			{
				return false;
			}
			return ColorUtility.TryParseHtmlString("#" + value, ref color);
		}

		public static void SetItemColor(ItemData item, Color color)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (item?.m_customData != null)
			{
				item.m_customData["ArmorColor"] = ColorUtility.ToHtmlStringRGBA(color);
			}
		}

		public static void ClearItemColor(ItemData item)
		{
			item?.m_customData?.Remove("ArmorColor");
		}

		public static void BroadcastColor(Player player, string itemName, Color color)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			ZNetView component = ((Component)player).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid())
			{
				component.InvokeRPC(ZNetView.Everybody, "ArmorColors_Sync", new object[1] { itemName + "|" + ColorUtility.ToHtmlStringRGBA(color) });
			}
		}

		public static void BroadcastReset(Player player, string itemName)
		{
			ZNetView component = ((Component)player).GetComponent<ZNetView>();
			if (!((Object)(object)component == (Object)null) && component.IsValid())
			{
				component.InvokeRPC(ZNetView.Everybody, "ArmorColors_Sync", new object[1] { itemName + "|RESET" });
			}
		}
	}
	public static class VisEquipmentPatch
	{
		public static string GetCharacterName(Player player)
		{
			string playerName = player.GetPlayerName();
			return string.IsNullOrEmpty(playerName) ? null : playerName;
		}
	}
}